mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-29 07:25:51 +00:00
Optimize trust line caching:
The existing trust line caching code was suboptimal in that it stored redundant information, pinned SLEs into memory and required multiple memory allocations per cached object. This commit eliminates redundant data, reducing the size of cached objects and unpinning SLEs from memory, and uses value_types to avoid the need for `std::shared_ptr`. As a result of these changes, the effective size of a cached object, includes the overhead of the memory allocator and the `std::shared_ptr` should be reduced by at least 64 bytes. This is significant, as there can easily be tens of millions of these objects.
This commit is contained in:
@@ -395,7 +395,7 @@ target_sources (rippled PRIVATE
|
||||
src/ripple/app/paths/Pathfinder.cpp
|
||||
src/ripple/app/paths/RippleCalc.cpp
|
||||
src/ripple/app/paths/RippleLineCache.cpp
|
||||
src/ripple/app/paths/RippleState.cpp
|
||||
src/ripple/app/paths/TrustLine.cpp
|
||||
src/ripple/app/paths/impl/BookStep.cpp
|
||||
src/ripple/app/paths/impl/DirectStep.cpp
|
||||
src/ripple/app/paths/impl/PaySteps.cpp
|
||||
|
||||
@@ -33,24 +33,16 @@ accountSourceCurrencies(
|
||||
if (includeXRP)
|
||||
currencies.insert(xrpCurrency());
|
||||
|
||||
// List of ripple lines.
|
||||
auto& rippleLines = lrCache->getRippleLines(account);
|
||||
|
||||
for (auto const& item : rippleLines)
|
||||
for (auto const& rspEntry : lrCache->getRippleLines(account))
|
||||
{
|
||||
auto rspEntry = (RippleState*)item.get();
|
||||
assert(rspEntry);
|
||||
if (!rspEntry)
|
||||
continue;
|
||||
|
||||
auto& saBalance = rspEntry->getBalance();
|
||||
auto& saBalance = rspEntry.getBalance();
|
||||
|
||||
// Filter out non
|
||||
if (saBalance > beast::zero
|
||||
// Have IOUs to send.
|
||||
|| (rspEntry->getLimitPeer()
|
||||
|| (rspEntry.getLimitPeer()
|
||||
// Peer extends credit.
|
||||
&& ((-saBalance) < rspEntry->getLimitPeer()))) // Credit left.
|
||||
&& ((-saBalance) < rspEntry.getLimitPeer()))) // Credit left.
|
||||
{
|
||||
currencies.insert(saBalance.getCurrency());
|
||||
}
|
||||
@@ -72,19 +64,11 @@ accountDestCurrencies(
|
||||
currencies.insert(xrpCurrency());
|
||||
// Even if account doesn't exist
|
||||
|
||||
// List of ripple lines.
|
||||
auto& rippleLines = lrCache->getRippleLines(account);
|
||||
|
||||
for (auto const& item : rippleLines)
|
||||
for (auto const& rspEntry : lrCache->getRippleLines(account))
|
||||
{
|
||||
auto rspEntry = (RippleState*)item.get();
|
||||
assert(rspEntry);
|
||||
if (!rspEntry)
|
||||
continue;
|
||||
auto& saBalance = rspEntry.getBalance();
|
||||
|
||||
auto& saBalance = rspEntry->getBalance();
|
||||
|
||||
if (saBalance < rspEntry->getLimit()) // Can take more
|
||||
if (saBalance < rspEntry.getLimit()) // Can take more
|
||||
currencies.insert(saBalance.getCurrency());
|
||||
}
|
||||
|
||||
|
||||
@@ -717,30 +717,27 @@ Pathfinder::getPathsOut(
|
||||
{
|
||||
count = app_.getOrderBookDB().getBookSize(issue);
|
||||
|
||||
for (auto const& item : mRLCache->getRippleLines(account))
|
||||
for (auto const& rspEntry : mRLCache->getRippleLines(account))
|
||||
{
|
||||
RippleState* rspEntry = (RippleState*)item.get();
|
||||
|
||||
if (currency != rspEntry->getLimit().getCurrency())
|
||||
if (currency != rspEntry.getLimit().getCurrency())
|
||||
{
|
||||
}
|
||||
else if (
|
||||
rspEntry->getBalance() <= beast::zero &&
|
||||
(!rspEntry->getLimitPeer() ||
|
||||
-rspEntry->getBalance() >= rspEntry->getLimitPeer() ||
|
||||
(bAuthRequired && !rspEntry->getAuth())))
|
||||
rspEntry.getBalance() <= beast::zero &&
|
||||
(!rspEntry.getLimitPeer() ||
|
||||
-rspEntry.getBalance() >= rspEntry.getLimitPeer() ||
|
||||
(bAuthRequired && !rspEntry.getAuth())))
|
||||
{
|
||||
}
|
||||
else if (
|
||||
isDstCurrency && dstAccount == rspEntry->getAccountIDPeer())
|
||||
else if (isDstCurrency && dstAccount == rspEntry.getAccountIDPeer())
|
||||
{
|
||||
count += 10000; // count a path to the destination extra
|
||||
}
|
||||
else if (rspEntry->getNoRipplePeer())
|
||||
else if (rspEntry.getNoRipplePeer())
|
||||
{
|
||||
// This probably isn't a useful path out
|
||||
}
|
||||
else if (rspEntry->getFreezePeer())
|
||||
else if (rspEntry.getFreezePeer())
|
||||
{
|
||||
// Not a useful path out
|
||||
}
|
||||
@@ -940,15 +937,9 @@ Pathfinder::addLink(
|
||||
AccountCandidates candidates;
|
||||
candidates.reserve(rippleLines.size());
|
||||
|
||||
for (auto const& item : rippleLines)
|
||||
for (auto const& rs : rippleLines)
|
||||
{
|
||||
auto* rs = dynamic_cast<RippleState const*>(item.get());
|
||||
if (!rs)
|
||||
{
|
||||
JLOG(j_.error()) << "Couldn't decipher RippleState";
|
||||
continue;
|
||||
}
|
||||
auto const& acct = rs->getAccountIDPeer();
|
||||
auto const& acct = rs.getAccountIDPeer();
|
||||
|
||||
if (hasEffectiveDestination && (acct == mDstAccount))
|
||||
{
|
||||
@@ -963,18 +954,18 @@ Pathfinder::addLink(
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((uEndCurrency == rs->getLimit().getCurrency()) &&
|
||||
if ((uEndCurrency == rs.getLimit().getCurrency()) &&
|
||||
!currentPath.hasSeen(acct, uEndCurrency, acct))
|
||||
{
|
||||
// path is for correct currency and has not been seen
|
||||
if (rs->getBalance() <= beast::zero &&
|
||||
(!rs->getLimitPeer() ||
|
||||
-rs->getBalance() >= rs->getLimitPeer() ||
|
||||
(bRequireAuth && !rs->getAuth())))
|
||||
if (rs.getBalance() <= beast::zero &&
|
||||
(!rs.getLimitPeer() ||
|
||||
-rs.getBalance() >= rs.getLimitPeer() ||
|
||||
(bRequireAuth && !rs.getAuth())))
|
||||
{
|
||||
// path has no credit
|
||||
}
|
||||
else if (bIsNoRippleOut && rs->getNoRipple())
|
||||
else if (bIsNoRippleOut && rs.getNoRipple())
|
||||
{
|
||||
// Can't leave on this path
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/paths/RippleLineCache.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/ledger/OpenView.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -30,18 +31,17 @@ RippleLineCache::RippleLineCache(std::shared_ptr<ReadView const> const& ledger)
|
||||
mLedger = std::make_shared<OpenView>(&*ledger, ledger);
|
||||
}
|
||||
|
||||
std::vector<RippleState::pointer> const&
|
||||
std::vector<PathFindTrustLine> const&
|
||||
RippleLineCache::getRippleLines(AccountID const& accountID)
|
||||
{
|
||||
AccountKey key(accountID, hasher_(accountID));
|
||||
|
||||
std::lock_guard sl(mLock);
|
||||
|
||||
auto [it, inserted] =
|
||||
lines_.emplace(key, std::vector<RippleState::pointer>());
|
||||
auto [it, inserted] = lines_.emplace(key, std::vector<PathFindTrustLine>());
|
||||
|
||||
if (inserted)
|
||||
it->second = getRippleStateItems(accountID, *mLedger);
|
||||
it->second = PathFindTrustLine::getItems(accountID, *mLedger);
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
#define RIPPLE_APP_PATHS_RIPPLELINECACHE_H_INCLUDED
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/basics/hardened_hash.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -31,7 +33,7 @@
|
||||
namespace ripple {
|
||||
|
||||
// Used by Pathfinder
|
||||
class RippleLineCache
|
||||
class RippleLineCache : public CountedObject<RippleLineCache>
|
||||
{
|
||||
public:
|
||||
explicit RippleLineCache(std::shared_ptr<ReadView const> const& l);
|
||||
@@ -42,7 +44,7 @@ public:
|
||||
return mLedger;
|
||||
}
|
||||
|
||||
std::vector<RippleState::pointer> const&
|
||||
std::vector<PathFindTrustLine> const&
|
||||
getRippleLines(AccountID const& accountID);
|
||||
|
||||
private:
|
||||
@@ -90,7 +92,7 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
hash_map<AccountKey, std::vector<RippleState::pointer>, AccountKey::Hash>
|
||||
hash_map<AccountKey, std::vector<PathFindTrustLine>, AccountKey::Hash>
|
||||
lines_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
RippleState::pointer
|
||||
RippleState::makeItem(
|
||||
AccountID const& accountID,
|
||||
std::shared_ptr<SLE const> sle)
|
||||
{
|
||||
// VFALCO Does this ever happen in practice?
|
||||
if (!sle || sle->getType() != ltRIPPLE_STATE)
|
||||
return {};
|
||||
return std::make_shared<RippleState>(std::move(sle), accountID);
|
||||
}
|
||||
|
||||
RippleState::RippleState(
|
||||
std::shared_ptr<SLE const>&& sle,
|
||||
AccountID const& viewAccount)
|
||||
: sle_(std::move(sle))
|
||||
, mFlags(sle_->getFieldU32(sfFlags))
|
||||
, mLowLimit(sle_->getFieldAmount(sfLowLimit))
|
||||
, mHighLimit(sle_->getFieldAmount(sfHighLimit))
|
||||
, mLowID(mLowLimit.getIssuer())
|
||||
, mHighID(mHighLimit.getIssuer())
|
||||
, lowQualityIn_(sle_->getFieldU32(sfLowQualityIn))
|
||||
, lowQualityOut_(sle_->getFieldU32(sfLowQualityOut))
|
||||
, highQualityIn_(sle_->getFieldU32(sfHighQualityIn))
|
||||
, highQualityOut_(sle_->getFieldU32(sfHighQualityOut))
|
||||
, mBalance(sle_->getFieldAmount(sfBalance))
|
||||
{
|
||||
mViewLowest = (mLowID == viewAccount);
|
||||
|
||||
if (!mViewLowest)
|
||||
mBalance.negate();
|
||||
}
|
||||
|
||||
Json::Value
|
||||
RippleState::getJson(int)
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["low_id"] = to_string(mLowID);
|
||||
ret["high_id"] = to_string(mHighID);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<RippleState::pointer>
|
||||
getRippleStateItems(AccountID const& accountID, ReadView const& view)
|
||||
{
|
||||
std::vector<RippleState::pointer> items;
|
||||
forEachItem(
|
||||
view,
|
||||
accountID,
|
||||
[&items, &accountID](std::shared_ptr<SLE const> const& sleCur) {
|
||||
auto ret = RippleState::makeItem(accountID, sleCur);
|
||||
if (ret)
|
||||
items.push_back(ret);
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
113
src/ripple/app/paths/TrustLine.cpp
Normal file
113
src/ripple/app/paths/TrustLine.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
TrustLineBase::TrustLineBase(
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
AccountID const& viewAccount)
|
||||
: key_(sle->key())
|
||||
, mLowLimit(sle->getFieldAmount(sfLowLimit))
|
||||
, mHighLimit(sle->getFieldAmount(sfHighLimit))
|
||||
, mBalance(sle->getFieldAmount(sfBalance))
|
||||
, mFlags(sle->getFieldU32(sfFlags))
|
||||
, mViewLowest(mLowLimit.getIssuer() == viewAccount)
|
||||
{
|
||||
if (!mViewLowest)
|
||||
mBalance.negate();
|
||||
}
|
||||
|
||||
Json::Value
|
||||
TrustLineBase::getJson(int)
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["low_id"] = to_string(mLowLimit.getIssuer());
|
||||
ret["high_id"] = to_string(mHighLimit.getIssuer());
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<PathFindTrustLine>
|
||||
PathFindTrustLine::makeItem(
|
||||
AccountID const& accountID,
|
||||
std::shared_ptr<SLE const> const& sle)
|
||||
{
|
||||
if (!sle || sle->getType() != ltRIPPLE_STATE)
|
||||
return {};
|
||||
return std::optional{PathFindTrustLine{sle, accountID}};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
std::vector<T>
|
||||
getTrustLineItems(AccountID const& accountID, ReadView const& view)
|
||||
{
|
||||
std::vector<T> items;
|
||||
forEachItem(
|
||||
view,
|
||||
accountID,
|
||||
[&items, &accountID](std::shared_ptr<SLE const> const& sleCur) {
|
||||
auto ret = T::makeItem(accountID, sleCur);
|
||||
if (ret)
|
||||
items.push_back(std::move(*ret));
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
std::vector<PathFindTrustLine>
|
||||
PathFindTrustLine::getItems(AccountID const& accountID, ReadView const& view)
|
||||
{
|
||||
return detail::getTrustLineItems<PathFindTrustLine>(accountID, view);
|
||||
}
|
||||
|
||||
RPCTrustLine::RPCTrustLine(
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
AccountID const& viewAccount)
|
||||
: TrustLineBase(sle, viewAccount)
|
||||
, lowQualityIn_(sle->getFieldU32(sfLowQualityIn))
|
||||
, lowQualityOut_(sle->getFieldU32(sfLowQualityOut))
|
||||
, highQualityIn_(sle->getFieldU32(sfHighQualityIn))
|
||||
, highQualityOut_(sle->getFieldU32(sfHighQualityOut))
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<RPCTrustLine>
|
||||
RPCTrustLine::makeItem(
|
||||
AccountID const& accountID,
|
||||
std::shared_ptr<SLE const> const& sle)
|
||||
{
|
||||
if (!sle || sle->getType() != ltRIPPLE_STATE)
|
||||
return {};
|
||||
return std::optional{RPCTrustLine{sle, accountID}};
|
||||
}
|
||||
|
||||
std::vector<RPCTrustLine>
|
||||
RPCTrustLine::getItems(AccountID const& accountID, ReadView const& view)
|
||||
{
|
||||
return detail::getTrustLineItems<RPCTrustLine>(accountID, view);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -20,12 +20,14 @@
|
||||
#ifndef RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED
|
||||
#define RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/protocol/Rate.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory> // <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -34,30 +36,32 @@ namespace ripple {
|
||||
"low" account and a "high" account. This wraps the
|
||||
SLE and expresses its data from the perspective of
|
||||
a chosen account on the line.
|
||||
|
||||
This wrapper is primarily used in the path finder and there can easily be
|
||||
tens of millions of instances of this class. When modifying this class think
|
||||
carefully about the memory implications.
|
||||
*/
|
||||
// VFALCO TODO Rename to TrustLine
|
||||
class RippleState
|
||||
class TrustLineBase
|
||||
{
|
||||
public:
|
||||
// VFALCO Why is this shared_ptr?
|
||||
using pointer = std::shared_ptr<RippleState>;
|
||||
protected:
|
||||
// This class should not be instantiated directly. Use one of the derived
|
||||
// classes.
|
||||
TrustLineBase(
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
AccountID const& viewAccount);
|
||||
|
||||
~TrustLineBase() = default;
|
||||
TrustLineBase(TrustLineBase const&) = default;
|
||||
TrustLineBase&
|
||||
operator=(TrustLineBase const&) = delete;
|
||||
TrustLineBase(TrustLineBase&&) = default;
|
||||
|
||||
public:
|
||||
RippleState() = delete;
|
||||
|
||||
virtual ~RippleState() = default;
|
||||
|
||||
static RippleState::pointer
|
||||
makeItem(AccountID const& accountID, std::shared_ptr<SLE const> sle);
|
||||
|
||||
// Must be public, for make_shared
|
||||
RippleState(std::shared_ptr<SLE const>&& sle, AccountID const& viewAccount);
|
||||
|
||||
/** Returns the state map key for the ledger entry. */
|
||||
uint256
|
||||
uint256 const&
|
||||
key() const
|
||||
{
|
||||
return sle_->key();
|
||||
return key_;
|
||||
}
|
||||
|
||||
// VFALCO Take off the "get" from each function name
|
||||
@@ -65,13 +69,13 @@ public:
|
||||
AccountID const&
|
||||
getAccountID() const
|
||||
{
|
||||
return mViewLowest ? mLowID : mHighID;
|
||||
return mViewLowest ? mLowLimit.getIssuer() : mHighLimit.getIssuer();
|
||||
}
|
||||
|
||||
AccountID const&
|
||||
getAccountIDPeer() const
|
||||
{
|
||||
return !mViewLowest ? mLowID : mHighID;
|
||||
return !mViewLowest ? mLowLimit.getIssuer() : mHighLimit.getIssuer();
|
||||
}
|
||||
|
||||
// True, Provided auth to peer.
|
||||
@@ -137,6 +141,52 @@ public:
|
||||
return !mViewLowest ? mLowLimit : mHighLimit;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
getJson(int);
|
||||
|
||||
protected:
|
||||
uint256 key_;
|
||||
|
||||
STAmount const mLowLimit;
|
||||
STAmount const mHighLimit;
|
||||
|
||||
STAmount mBalance;
|
||||
|
||||
std::uint32_t mFlags;
|
||||
|
||||
bool mViewLowest;
|
||||
};
|
||||
|
||||
// This wrapper is used for the path finder
|
||||
class PathFindTrustLine final : public TrustLineBase,
|
||||
public CountedObject<PathFindTrustLine>
|
||||
{
|
||||
using TrustLineBase::TrustLineBase;
|
||||
|
||||
public:
|
||||
PathFindTrustLine() = delete;
|
||||
|
||||
static std::optional<PathFindTrustLine>
|
||||
makeItem(AccountID const& accountID, std::shared_ptr<SLE const> const& sle);
|
||||
|
||||
static std::vector<PathFindTrustLine>
|
||||
getItems(AccountID const& accountID, ReadView const& view);
|
||||
};
|
||||
|
||||
// This wrapper is used for the `AccountLines` command and includes the quality
|
||||
// in and quality out values.
|
||||
class RPCTrustLine final : public TrustLineBase,
|
||||
public CountedObject<RPCTrustLine>
|
||||
{
|
||||
using TrustLineBase::TrustLineBase;
|
||||
|
||||
public:
|
||||
RPCTrustLine() = delete;
|
||||
|
||||
RPCTrustLine(
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
AccountID const& viewAccount);
|
||||
|
||||
Rate const&
|
||||
getQualityIn() const
|
||||
{
|
||||
@@ -149,33 +199,19 @@ public:
|
||||
return mViewLowest ? lowQualityOut_ : highQualityOut_;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
getJson(int);
|
||||
static std::optional<RPCTrustLine>
|
||||
makeItem(AccountID const& accountID, std::shared_ptr<SLE const> const& sle);
|
||||
|
||||
static std::vector<RPCTrustLine>
|
||||
getItems(AccountID const& accountID, ReadView const& view);
|
||||
|
||||
private:
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
|
||||
bool mViewLowest;
|
||||
|
||||
std::uint32_t mFlags;
|
||||
|
||||
STAmount const& mLowLimit;
|
||||
STAmount const& mHighLimit;
|
||||
|
||||
AccountID const& mLowID;
|
||||
AccountID const& mHighID;
|
||||
|
||||
Rate lowQualityIn_;
|
||||
Rate lowQualityOut_;
|
||||
Rate highQualityIn_;
|
||||
Rate highQualityOut_;
|
||||
|
||||
STAmount mBalance;
|
||||
};
|
||||
|
||||
std::vector<RippleState::pointer>
|
||||
getRippleStateItems(AccountID const& accountID, ReadView const& view);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
@@ -58,15 +58,13 @@ doAccountCurrencies(RPC::JsonContext& context)
|
||||
return rpcError(rpcACT_NOT_FOUND);
|
||||
|
||||
std::set<Currency> send, receive;
|
||||
for (auto const& item : getRippleStateItems(accountID, *ledger))
|
||||
for (auto const& rspEntry : RPCTrustLine::getItems(accountID, *ledger))
|
||||
{
|
||||
auto const rspEntry = item.get();
|
||||
STAmount const& saBalance = rspEntry.getBalance();
|
||||
|
||||
STAmount const& saBalance = rspEntry->getBalance();
|
||||
|
||||
if (saBalance < rspEntry->getLimit())
|
||||
if (saBalance < rspEntry.getLimit())
|
||||
receive.insert(saBalance.getCurrency());
|
||||
if ((-saBalance) < rspEntry->getLimitPeer())
|
||||
if ((-saBalance) < rspEntry.getLimitPeer())
|
||||
send.insert(saBalance.getCurrency());
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
@@ -32,18 +32,17 @@ namespace ripple {
|
||||
|
||||
struct VisitData
|
||||
{
|
||||
std::vector<RippleState::pointer> items;
|
||||
std::vector<RPCTrustLine> items;
|
||||
AccountID const& accountID;
|
||||
bool hasPeer;
|
||||
AccountID const& raPeerAccount;
|
||||
|
||||
bool ignoreDefault;
|
||||
uint32_t foundCount;
|
||||
RippleState::pointer lastFound;
|
||||
};
|
||||
|
||||
void
|
||||
addLine(Json::Value& jsonLines, RippleState const& line)
|
||||
addLine(Json::Value& jsonLines, RPCTrustLine const& line)
|
||||
{
|
||||
STAmount const& saBalance(line.getBalance());
|
||||
STAmount const& saLimit(line.getLimit());
|
||||
@@ -140,7 +139,7 @@ doAccountLines(RPC::JsonContext& context)
|
||||
|
||||
Json::Value& jsonLines(result[jss::lines] = Json::arrayValue);
|
||||
VisitData visitData = {
|
||||
{}, accountID, hasPeer, raPeerAccount, ignoreDefault, 0, nullptr};
|
||||
{}, accountID, hasPeer, raPeerAccount, ignoreDefault, 0};
|
||||
uint256 startAfter = beast::zero;
|
||||
std::uint64_t startHint = 0;
|
||||
|
||||
@@ -194,18 +193,6 @@ doAccountLines(RPC::JsonContext& context)
|
||||
limit + 1,
|
||||
[&visitData, &count, &marker, &limit, &nextHint](
|
||||
std::shared_ptr<SLE const> const& sleCur) {
|
||||
bool ignore = false;
|
||||
if (visitData.ignoreDefault)
|
||||
{
|
||||
if (sleCur->getFieldAmount(sfLowLimit).getIssuer() ==
|
||||
visitData.accountID)
|
||||
ignore =
|
||||
!(sleCur->getFieldU32(sfFlags) & lsfLowReserve);
|
||||
else
|
||||
ignore = !(
|
||||
sleCur->getFieldU32(sfFlags) & lsfHighReserve);
|
||||
}
|
||||
|
||||
if (!sleCur)
|
||||
{
|
||||
assert(false);
|
||||
@@ -219,17 +206,32 @@ doAccountLines(RPC::JsonContext& context)
|
||||
RPC::getStartHint(sleCur, visitData.accountID);
|
||||
}
|
||||
|
||||
if (sleCur->getType() != ltRIPPLE_STATE)
|
||||
return true;
|
||||
|
||||
bool ignore = false;
|
||||
if (visitData.ignoreDefault)
|
||||
{
|
||||
if (sleCur->getFieldAmount(sfLowLimit).getIssuer() ==
|
||||
visitData.accountID)
|
||||
ignore =
|
||||
!(sleCur->getFieldU32(sfFlags) & lsfLowReserve);
|
||||
else
|
||||
ignore = !(
|
||||
sleCur->getFieldU32(sfFlags) & lsfHighReserve);
|
||||
}
|
||||
|
||||
if (!ignore && count <= limit)
|
||||
{
|
||||
auto const line =
|
||||
RippleState::makeItem(visitData.accountID, sleCur);
|
||||
RPCTrustLine::makeItem(visitData.accountID, sleCur);
|
||||
|
||||
if (line != nullptr &&
|
||||
if (line &&
|
||||
(!visitData.hasPeer ||
|
||||
visitData.raPeerAccount ==
|
||||
line->getAccountIDPeer()))
|
||||
{
|
||||
visitData.items.emplace_back(line);
|
||||
visitData.items.emplace_back(*line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +255,7 @@ doAccountLines(RPC::JsonContext& context)
|
||||
result[jss::account] = context.app.accountIDCache().toBase58(accountID);
|
||||
|
||||
for (auto const& item : visitData.items)
|
||||
addLine(jsonLines, *item.get());
|
||||
addLine(jsonLines, item);
|
||||
|
||||
context.loadType = Resource::feeMediumBurdenRPC;
|
||||
return result;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/AccountID.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
@@ -144,7 +144,7 @@ doGatewayBalances(RPC::JsonContext& context)
|
||||
{
|
||||
forEachItem(
|
||||
*ledger, accountID, [&](std::shared_ptr<SLE const> const& sle) {
|
||||
auto rs = RippleState::makeItem(accountID, sle);
|
||||
auto rs = PathFindTrustLine::makeItem(accountID, sle);
|
||||
|
||||
if (!rs)
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <ripple/app/ledger/LedgerMaster.h>
|
||||
#include <ripple/app/ledger/OpenLedger.h>
|
||||
#include <ripple/app/misc/Transaction.h>
|
||||
#include <ripple/app/paths/RippleState.h>
|
||||
#include <ripple/app/paths/TrustLine.h>
|
||||
#include <ripple/app/rdb/RelationalDBInterface.h>
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
|
||||
Reference in New Issue
Block a user