xrpld
Loading...
Searching...
No Matches
AssetCache.cpp
1#include <xrpld/rpc/detail/AssetCache.h>
2
3#include <xrpld/rpc/detail/MPT.h>
4#include <xrpld/rpc/detail/TrustLine.h>
5
6#include <xrpl/basics/Log.h>
7#include <xrpl/beast/utility/Journal.h>
8#include <xrpl/beast/utility/instrumentation.h>
9#include <xrpl/ledger/ReadView.h>
10#include <xrpl/ledger/helpers/DirectoryHelpers.h>
11#include <xrpl/ledger/helpers/MPTokenHelpers.h>
12#include <xrpl/protocol/AccountID.h>
13#include <xrpl/protocol/Indexes.h>
14#include <xrpl/protocol/LedgerFormats.h>
15#include <xrpl/protocol/SField.h>
16#include <xrpl/protocol/STLedgerEntry.h>
17
18#include <memory>
19#include <mutex>
20#include <utility>
21#include <vector>
22
23namespace xrpl {
24
26 : ledger_(std::move(ledger)), journal_(j)
27{
28 JLOG(journal_.debug()) << "created for ledger " << ledger_->header().seq;
29}
30
32{
33 JLOG(journal_.debug()) << "destroyed for ledger " << ledger_->header().seq << " with "
34 << lines_.size() << " accounts and " << totalLineCount_
35 << " distinct trust lines.";
36}
37
40{
41 auto const hash = hasher_(accountID);
42 AccountKey key(accountID, direction, hash);
43 AccountKey otherkey(
44 accountID,
46 hash);
47
48 std::scoped_lock const sl(lock_);
49
50 auto [it, inserted] = [&]() {
51 if (auto otheriter = lines_.find(otherkey); otheriter != lines_.end())
52 {
53 // The whole point of using the direction flag is to reduce the
54 // number of trust line objects held in memory. Ensure that there is
55 // only a single set of trustlines in the cache per account.
56 auto const size = otheriter->second ? otheriter->second->size() : 0;
57 JLOG(journal_.info())
58 << "Request for "
59 << (direction == LineDirection::Outgoing ? "outgoing" : "incoming")
60 << " trust lines for account " << accountID << " found " << size
61 << (direction == LineDirection::Outgoing ? " incoming" : " outgoing")
62 << " trust lines. "
63 << (direction == LineDirection::Outgoing ? "Deleting the subset of incoming"
64 : "Returning the superset of outgoing")
65 << " trust lines. ";
66 if (direction == LineDirection::Outgoing)
67 {
68 // This request is for the outgoing set, but there is already a
69 // subset of incoming lines in the cache. Erase that subset
70 // to be replaced by the full set. The full set will be built
71 // below, and will be returned, if needed, on subsequent calls
72 // for either value of outgoing.
73 XRPL_ASSERT(
74 size <= totalLineCount_, "xrpl::AssetCache::getRippleLines : maximum lines");
75 totalLineCount_ -= size;
76 lines_.erase(otheriter);
77 }
78 else
79 {
80 // This request is for the incoming set, but there is
81 // already a superset of the outgoing trust lines in the cache.
82 // The path finding engine will disregard the non-rippling trust
83 // lines, so to prevent them from being stored twice, return the
84 // outgoing set.
85 key = otherkey;
86 return std::pair{otheriter, false};
87 }
88 }
89 return lines_.emplace(key, nullptr);
90 }();
91
92 if (inserted)
93 {
94 XRPL_ASSERT(it->second == nullptr, "xrpl::Asset::getRippleLines : null lines");
95 auto lines = PathFindTrustLine::getItems(accountID, *ledger_, direction);
96 if (!lines.empty())
97 {
98 it->second = std::make_shared<std::vector<PathFindTrustLine>>(std::move(lines));
99 totalLineCount_ += it->second->size();
100 }
101 }
102
103 XRPL_ASSERT(
104 !it->second || !it->second->empty(),
105 "xrpl::AssetCache::getRippleLines : null or nonempty lines");
106 auto const size = it->second ? it->second->size() : 0;
107 JLOG(journal_.trace()) << "getRippleLines for ledger " << ledger_->header().seq << " found "
108 << size
109 << (key.direction == LineDirection::Outgoing ? " outgoing" : " incoming")
110 << " lines for " << (inserted ? "new " : "existing ") << accountID
111 << " out of a total of " << lines_.size() << " accounts and "
112 << totalLineCount_ << " trust lines";
113
114 return it->second;
115}
116
119{
120 std::scoped_lock const sl(lock_);
121
122 if (auto it = mpts_.find(account); it != mpts_.end())
123 return it->second;
124
126 // Get issued/authorized tokens
127 forEachItem(*ledger_, account, [&](SLE::const_ref sle) {
128 if (sle->getType() == ltMPTOKEN_ISSUANCE)
129 {
130 auto const mptID = makeMptID(sle->getFieldU32(sfSequence), account);
131 bool const maxedOut = sle->at(sfOutstandingAmount) == maxMPTAmount(*sle);
132 mpts.emplace_back(mptID, false, maxedOut);
133 }
134 else if (sle->getType() == ltMPTOKEN)
135 {
136 auto const mptID = sle->getFieldH192(sfMPTokenIssuanceID);
137 bool const zeroBalance = sle->at(sfMPTAmount) == 0;
138 bool const maxedOut = [&] {
139 if (auto const sleIssuance = ledger_->read(keylet::mptokenIssuance(mptID)))
140 {
141 return sleIssuance->at(sfOutstandingAmount) == maxMPTAmount(*sleIssuance);
142 }
143 return true;
144 }();
145
146 mpts.emplace_back(mptID, zeroBalance, maxedOut);
147 }
148 });
149
150 if (mpts.empty())
151 {
152 mpts_.emplace(account, nullptr);
153 }
154 else
155 {
156 mpts_.emplace(account, std::make_shared<std::vector<PathFindMPT>>(std::move(mpts)));
157 }
158
159 return mpts_[account];
160}
161
162} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
AssetCache(std::shared_ptr< ReadView const > l, beast::Journal j)
beast::Journal journal_
Definition AssetCache.h:53
std::shared_ptr< std::vector< PathFindTrustLine > > getRippleLines(AccountID const &accountID, LineDirection direction)
Find the trust lines associated with an account.
hash_map< AccountID, std::shared_ptr< std::vector< PathFindMPT > > > mpts_
Definition AssetCache.h:103
std::shared_ptr< std::vector< PathFindMPT > > const & getMPTs(AccountID const &account)
xrpl::HardenedHash hasher_
Definition AssetCache.h:50
hash_map< AccountKey, std::shared_ptr< std::vector< PathFindTrustLine > >, AccountKey::Hash > lines_
Definition AssetCache.h:101
std::size_t totalLineCount_
Definition AssetCache.h:102
std::mutex lock_
Definition AssetCache.h:48
std::shared_ptr< ReadView const > ledger_
Definition AssetCache.h:51
static std::vector< PathFindTrustLine > getItems(AccountID const &accountID, ReadView const &view, LineDirection direction)
Definition TrustLine.cpp:69
std::shared_ptr< STLedgerEntry const > const & const_ref
T emplace_back(T... args)
T empty(T... args)
T make_shared(T... args)
STL namespace.
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:521
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::int64_t maxMPTAmount(SLE const &sleIssuance)
LineDirection
Describes how an account was found in a path, and how to find the next set of paths.
Definition TrustLine.h:21
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(SLE::const_ref)> const &f)
Iterate all items in the given directory.
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
Definition Indexes.cpp:172