1#include <xrpl/ledger/detail/ApplyStateTable.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/beast/utility/instrumentation.h>
8#include <xrpl/json/to_string.h>
9#include <xrpl/ledger/OpenView.h>
10#include <xrpl/ledger/RawView.h>
11#include <xrpl/ledger/ReadView.h>
12#include <xrpl/protocol/AccountID.h>
13#include <xrpl/protocol/Indexes.h>
14#include <xrpl/protocol/Keylet.h>
15#include <xrpl/protocol/LedgerFormats.h>
16#include <xrpl/protocol/Protocol.h>
17#include <xrpl/protocol/SField.h>
18#include <xrpl/protocol/STAmount.h>
19#include <xrpl/protocol/STLedgerEntry.h>
20#include <xrpl/protocol/STTx.h>
21#include <xrpl/protocol/Serializer.h>
22#include <xrpl/protocol/TER.h>
23#include <xrpl/protocol/TxMeta.h>
24#include <xrpl/protocol/XRPAmount.h>
41 for (
auto const& item :
items_)
43 auto const& sle = item.second.second;
44 switch (item.second.first)
67 switch (item.second.first)
89 switch (item.second.first)
96 func(item.first,
false,
nullptr, item.second.second);
124 if (!to.
open() || isDryRun)
134 SField const* type =
nullptr;
135 switch (item.second.first)
141 type = &sfDeletedNode;
144 type = &sfCreatedNode;
147 type = &sfModifiedNode;
151 auto curNode = item.second.second;
152 if ((type == &sfModifiedNode) && (*curNode == *origNode))
154 std::uint16_t const nodeType = curNode ? curNode->getFieldU16(sfLedgerEntryType)
155 : origNode->getFieldU16(sfLedgerEntryType);
157 if (type == &sfDeletedNode)
161 "xrpl::detail::ApplyStateTable::apply : valid nodes for "
166 for (
auto const& obj : *origNode)
171 !curNode->hasMatchingEntry(obj))
179 for (
auto const& obj : *curNode)
189 else if (type == &sfModifiedNode)
193 "xrpl::detail::ApplyStateTable::apply : valid nodes for "
196 if (curNode->isThreadedType(to.
rules()))
203 for (
auto const& obj : *origNode)
207 !curNode->hasMatchingEntry(obj))
215 for (
auto const& obj : *curNode)
225 else if (type == &sfCreatedNode)
228 curNode && !origNode,
229 "xrpl::detail::ApplyStateTable::apply : valid nodes for "
233 if (curNode->isThreadedType(to.
rules()))
237 for (
auto const& obj : *curNode)
240 if (!obj.isDefault() &&
252 "xrpl::detail::ApplyStateTable::apply : unsupported "
261 for (
auto const& mod : newMod)
291 auto const& item = iter->second;
292 auto const& sle = item.second;
302 return k.
check(*sle);
312 items_t::const_iterator iter;
317 next = base.succ(*next, last);
320 iter =
items_.find(*next);
323 for (iter =
items_.upper_bound(key); iter !=
items_.end(); ++iter)
328 if (!next || next > iter->first)
335 if (last && next >= last)
346 auto const& item = iter->second;
347 auto const& sle = item.second;
366 if (iter ==
items_.end() || iter->first != k.
key)
368 auto const sle = base.
read(k);
373 iter =
items_.emplace_hint(
378 return iter->second.second;
380 auto const& item = iter->second;
381 auto const& sle = item.second;
399 auto const iter =
items_.find(sle->key());
402 auto& item = iter->second;
403 if (item.second != sle)
424 auto const result =
items_.emplace(
428 auto& item = result.first->second;
435 items_.erase(result.first);
448 auto const iter =
items_.lower_bound(sle->key());
449 if (iter ==
items_.end() || iter->first != sle->key())
459 auto& item = iter->second;
478 auto const iter =
items_.lower_bound(sle->key());
479 if (iter ==
items_.end() || iter->first != sle->key())
489 auto& item = iter->second;
507 auto const iter =
items_.find(sle->key());
510 auto& item = iter->second;
511 if (item.second != sle)
549 if (node.getFieldIndex(sfPreviousTxnID) == -1)
552 node.getFieldIndex(sfPreviousTxnLgrSeq) == -1,
553 "xrpl::ApplyStateTable::threadItem : previous ledger is not "
555 node.setFieldH256(sfPreviousTxnID, prevTxID);
556 node.setFieldU32(sfPreviousTxnLgrSeq, prevLgrID);
560 node.getFieldH256(sfPreviousTxnID) == prevTxID,
561 "xrpl::ApplyStateTable::threadItem : previous transaction is a "
564 node.getFieldU32(sfPreviousTxnLgrSeq) == prevLgrID,
565 "xrpl::ApplyStateTable::threadItem : previous ledger is a match");
573 auto miter = mods.
find(key);
574 if (miter != mods.
end())
576 XRPL_ASSERT(miter->second,
"xrpl::ApplyStateTable::getForMod : non-null result");
577 return miter->second;
581 auto iter =
items_.find(key);
584 auto const& item = iter->second;
590 JLOG(j.
warn()) <<
"Trying to thread to deleted node";
606 JLOG(j.
warn()) <<
"ApplyStateTable::getForMod: key not found";
628 JLOG(j.
warn()) <<
"Threading to non-existent account: " <<
toBase58(to);
633 sle->isThreadedType(base.
rules()),
"xrpl::ApplyStateTable::threadTx : SLE is threaded");
648 case ltACCOUNT_ROOT: {
652 case ltRIPPLE_STATE: {
653 threadTx(base, meta, (*sle)[sfLowLimit].getIssuer(), mods, j);
654 threadTx(base, meta, (*sle)[sfHighLimit].getIssuer(), mods, j);
659 if (
auto const optSleAcct{(*sle)[~sfAccount]})
660 threadTx(base, meta, *optSleAcct, mods, j);
663 if (
auto const optSleDest{(*sle)[~sfDestination]})
664 threadTx(base, meta, *optSleDest, mods, j);
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writable ledger view that accumulates state and tx changes.
std::size_t txCount() const
Return the number of tx inserted since creation.
bool open() const override
Returns true if this reflects an open ledger.
SLE::const_pointer read(Keylet const &k) const override
Return the state item associated with a key.
void rawTxInsert(key_type const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Add a transaction to the tx map.
Rules const & rules() const override
Returns the tx processing rules.
void rawReplace(SLE::ref sle) override
Unconditionally replace a state item.
Interface for ledger entry changes.
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.
virtual Rules const & rules() const =0
Returns the tx processing rules.
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.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
static constexpr auto kSmdChangeOrig
static constexpr auto kSmdDeleteFinal
static constexpr auto kSmdCreate
static constexpr auto kSmdAlways
static constexpr auto kSmdChangeNew
std::shared_ptr< STLedgerEntry > const & ref
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
std::size_t emplaceBack(Args &&... args)
void add(Serializer &s) const override
uint256 getTransactionID() const
SLE::const_pointer read(ReadView const &base, Keylet const &k) const
void destroyXRP(XRPAmount const &fee)
bool exists(ReadView const &base, Keylet const &k) const
void replace(ReadView const &base, SLE::ref sle)
void insert(ReadView const &base, SLE::ref sle)
void visit(ReadView const &base, std::function< void(uint256 const &key, bool isDelete, SLE::const_ref before, SLE::const_ref after)> const &func) const
SLE::pointer peek(ReadView const &base, Keylet const &k)
SLE::pointer getForMod(ReadView const &base, key_type const &key, Mods &mods, beast::Journal j)
std::optional< key_type > succ(ReadView const &base, key_type const &key, std::optional< key_type > const &last) const
void threadTx(ReadView const &base, TxMeta &meta, AccountID const &to, Mods &mods, beast::Journal j)
void threadOwners(ReadView const &base, TxMeta &meta, SLE::const_ref sle, Mods &mods, beast::Journal j)
void rawErase(ReadView const &base, SLE::ref sle)
void apply(RawView &to) const
void update(ReadView const &base, SLE::ref sle)
hash_map< key_type, SLE::pointer > Mods
XRPAmount dropsDestroyed_
static void threadItem(TxMeta &meta, SLE::ref to)
void erase(ReadView const &base, SLE::ref sle)
ReadView::key_type key_type
T forward_as_tuple(T... args)
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet account(AccountID const &id) noexcept
AccountID root.
std::uint32_t LedgerIndex
A ledger index.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TERSubset< CanCvtToTER > TER
LedgerEntryType
Identifiers for on-ledger objects.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
A pair of SHAMap key and LedgerEntryType.
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.