Refactor Ledger and support classes:

This performs a deep refactor on the Ledger class and its supporting
classes, in preparation for the move to shared_ptr<SLE const> in
places where the SLE is immutable and we are currently using
shared_ptr<SLE>.

Member functions are converted to free functions, the SLECache is an
explicit parameter, one line convenience functions are removed to
streamline the interface. Some callers are changed to use <SLE const>
instead of <SLE>

SLECache:
* Moved to its own header file

RippleState:
* Remove unused functions
* Store the SLE as const
* Simplify callers

AccountState:
* Remove unused members
* Simplify existing members

Ledger:
* Replace writeBack with insert and update
* Remove unused functions
* Remove LedgerStateParams
* Move getLastFullLedger to Application
* add entryCacheI, exists, fetch, erase
* Use boost::optional where it makes sense
* Make member functions free functions

Free functions:
* fetch: cache-aware SLE retrieval
* forEachItem, forEachItemAfter
* (various)
This commit is contained in:
Vinnie Falco
2015-06-05 07:25:45 -07:00
parent 454d2f8c45
commit babaac9305
45 changed files with 1224 additions and 1129 deletions

View File

@@ -1480,6 +1480,8 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\PendingSaves.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\SLECache.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\tests\common_ledger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>

View File

@@ -2205,6 +2205,9 @@
<ClInclude Include="..\..\src\ripple\app\ledger\PendingSaves.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\SLECache.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\tests\common_ledger.cpp">
<Filter>ripple\app\ledger\tests</Filter>
</ClCompile>

View File

@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}"
Project("{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}") = "RippleD", "RippleD.vcxproj", "{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -45,7 +45,7 @@ AcceptedLedger::AcceptedLedger (Ledger::ref ledger) : mLedger (ledger)
AcceptedLedger::pointer AcceptedLedger::makeAcceptedLedger (Ledger::ref ledger)
{
AcceptedLedger::pointer ret = s_cache.fetch (ledger->getHash ());
AcceptedLedger::pointer ret = s_cache.fetch (ledger->getHash());
if (ret)
return ret;

File diff suppressed because it is too large Load Diff

View File

@@ -23,40 +23,34 @@
#include <ripple/shamap/SHAMap.h>
#include <ripple/app/tx/Transaction.h>
#include <ripple/app/tx/TransactionMeta.h>
#include <ripple/app/ledger/SLECache.h>
#include <ripple/app/misc/AccountState.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/Book.h>
#include <beast/utility/Journal.h>
#include <boost/optional.hpp>
#include <mutex>
namespace ripple {
class Job;
enum LedgerStateParms
{
lepNONE = 0, // no special flags
// input flags
lepCREATE = 1, // Create if not present
// output flags
lepOKAY = 2, // success
lepMISSING = 4, // No node in that slot
lepWRONGTYPE = 8, // Node of different type there
lepCREATED = 16, // Node was created
lepERROR = 32, // error
};
class SqliteStatement;
// VFALCO TODO figure out exactly how this thing works.
// It seems like some ledger database is stored as a global, static in
// the class. But then what is the meaning of a Ledger object? Is this
// really two classes in one? StoreOfAllLedgers + SingleLedgerObject?
//
/** Holds some or all of a ledger.
/** Holds a ledger.
The ledger is composed of two SHAMaps. The state map holds all of the
ledger entries such as account roots and order books. The tx map holds
all of the transactions and associated metadata that made it into that
particular ledger. Most of the operations on a ledger are concerned
with the state map.
A View provides a structured interface to manipulate the state map in
a reversible way, with facilities to automatically produce metadata
when applying changes.
This can hold just the header, a partial set of data, or the entire set
of data. It all depends on what is in the corresponding SHAMap entry.
Various functions are provided to populate or depopulate the caches that
@@ -82,42 +76,12 @@ public:
using pointer = std::shared_ptr<Ledger>;
using ref = const std::shared_ptr<Ledger>&;
enum TransResult
{
TR_ERROR = -1,
TR_SUCCESS = 0,
TR_NOTFOUND = 1,
TR_ALREADY = 2,
// the transaction itself is corrupt
TR_BADTRANS = 3,
// one of the accounts is invalid
TR_BADACCT = 4,
// the sending(apply)/receiving(remove) account is broke
TR_INSUFF = 5,
// account is past this transaction
TR_PASTASEQ = 6,
// account is missing transactions before this
TR_PREASEQ = 7,
// ledger too early
TR_BADLSEQ = 8,
// amount is less than Tx fee
TR_TOOSMALL = 9,
};
// ledger close flags
static const std::uint32_t sLCF_NoConsensusTime = 1;
public:
Ledger (Ledger const&) = delete;
Ledger& operator= (Ledger const&) = delete;
// used for the starting bootstrap ledger
Ledger (const RippleAddress & masterID, std::uint64_t startAmount);
Ledger (RippleAddress const& masterID,
std::uint64_t startAmount);
// Used for ledgers loaded from JSON files
Ledger (uint256 const& parentHash, uint256 const& transHash,
@@ -125,106 +89,196 @@ public:
std::uint64_t totCoins, std::uint32_t closeTime,
std::uint32_t parentCloseTime, int closeFlags, int closeResolution,
std::uint32_t ledgerSeq, bool & loaded);
// used for database ledgers
// used for database ledgers
Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime);
Ledger (void const* data,
std::size_t size, bool hasPrefix);
Ledger (bool dummy, Ledger & previous); // ledger after this one
Ledger (Ledger & target, bool isMutable); // snapshot
Ledger (Ledger const&) = delete;
Ledger& operator= (Ledger const&) = delete;
// Create a new ledger that follows this one
// VFALCO `previous` should be const
Ledger (bool dummy, Ledger& previous);
~Ledger ();
// Create a new ledger that's a snapshot of this one
Ledger (Ledger const& target, bool isMutable);
static Ledger::pointer getLastFullLedger ();
~Ledger();
//--------------------------------------------------------------------------
/** Returns `true` if a ledger entry exists. */
bool
exists (uint256 const& key) const;
/** Return the state item for a key.
The item may not be modified.
@return The serialized ledger entry or empty
if the key does not exist.
*/
std::shared_ptr<SHAMapItem const>
find (uint256 const& key) const;
/** Add a new state SLE.
Effects:
assert if the key already exists.
The key in the state map is associated
with an unflattened copy of the SLE.
@note The key is taken from the SLE.
*/
void
insert (SLE const& sle);
/** Fetch a modifiable state SLE.
Effects:
Gives the caller ownership of an
unflattened copy of the SLE.
@param type An optional LedgerEntryType. If type is
engaged and the SLE's type does not match,
then boost::none is returned.
@return `empty` if the key is not present
*/
boost::optional<SLE>
fetch (uint256 const& key, boost::optional<
LedgerEntryType> type = boost::none) const;
// DEPRECATED
// Retrieve immutable ledger entry
SLE::pointer getSLEi (uint256 const& uHash) const;
/** Replace an existing state SLE.
Effects:
assert if key does not already exist.
The previous flattened SLE associated with
the key is released.
The key in the state map is associated
with a flattened copy of the SLE.
@note The key is taken from the SLE
*/
void
replace (SLE const& sle);
/** Remove an state SLE.
Effects:
assert if the key does not exist.
The flattened SLE associated with the key
is released from the state map.
*/
void
erase (uint256 const& key);
//--------------------------------------------------------------------------
void updateHash ();
void setClosed ()
{
mClosed = true;
}
void setValidated()
{
mValidated = true;
}
void setAccepted (
std::uint32_t closeTime, int closeResolution, bool correctCloseTime);
void setAccepted (std::uint32_t closeTime,
int closeResolution, bool correctCloseTime);
void setAccepted ();
void setImmutable ();
bool isClosed () const
{
return mClosed;
}
bool isAccepted () const
{
return mAccepted;
}
bool isValidated () const
{
return mValidated;
}
bool isImmutable () const
{
return mImmutable;
}
bool isFixed () const
{
return mClosed || mImmutable;
}
void setFull ()
{
mTransactionMap->setLedgerSeq (mLedgerSeq);
mAccountStateMap->setLedgerSeq (mLedgerSeq);
mTransactionMap->setLedgerSeq (seq_);
mAccountStateMap->setLedgerSeq (seq_);
}
// ledger signature operations
void addRaw (Serializer& s) const;
void setRaw (SerialIter& sit, bool hasPrefix);
uint256 const& getHash ();
/** Return the hash of the ledger.
This will recalculate the hash if necessary.
*/
uint256 const&
getHash();
uint256 const& getParentHash () const
{
return mParentHash;
}
uint256 const& getTransHash () const
{
return mTransHash;
}
uint256 const& getAccountHash () const
{
return mAccountHash;
}
std::uint64_t getTotalCoins () const
{
return mTotCoins;
}
void destroyCoins (std::uint64_t fee)
{
mTotCoins -= fee;
}
void setTotalCoins (std::uint64_t totCoins)
{
mTotCoins = totCoins;
}
std::uint32_t getCloseTimeNC () const
{
return mCloseTime;
}
std::uint32_t getParentCloseTimeNC () const
{
return mParentCloseTime;
}
LedgerIndex
seq() const
{
return seq_;
}
// DEPRECATED
std::uint32_t getLedgerSeq () const
{
return mLedgerSeq;
return seq_;
}
int getCloseResolution () const
{
return mCloseResolution;
}
bool getCloseAgree () const
{
return (mCloseFlags & sLCF_NoConsensusTime) == 0;
@@ -236,7 +290,9 @@ public:
assert (!mImmutable);
mCloseTime = ct;
}
void setCloseTime (boost::posix_time::ptime);
boost::posix_time::ptime getCloseTime () const;
// low level functions
@@ -244,6 +300,7 @@ public:
{
return mTransactionMap;
}
std::shared_ptr<SHAMap> const& peekAccountStateMap () const
{
return mAccountStateMap;
@@ -260,104 +317,55 @@ public:
// Transaction Functions
bool addTransaction (uint256 const& id, Serializer const& txn);
bool addTransaction (
uint256 const& id, Serializer const& txn, Serializer const& metaData);
bool hasTransaction (uint256 const& TransID) const
{
return mTransactionMap->hasItem (TransID);
}
Transaction::pointer getTransaction (uint256 const& transID) const;
bool getTransaction (
uint256 const& transID,
Transaction::pointer & txn, TransactionMetaSet::pointer & txMeta) const;
bool getTransactionMeta (
uint256 const& transID, TransactionMetaSet::pointer & txMeta) const;
bool getMetaHex (uint256 const& transID, std::string & hex) const;
static STTx::pointer getSTransaction (
std::shared_ptr<SHAMapItem> const&, SHAMapTreeNode::TNType);
STTx::pointer getSMTransaction (
std::shared_ptr<SHAMapItem> const&, SHAMapTreeNode::TNType,
TransactionMetaSet::pointer & txMeta) const;
// high-level functions
bool hasAccount (const RippleAddress & acctID) const;
AccountState::pointer getAccountState (const RippleAddress & acctID) const;
LedgerStateParms writeBack (LedgerStateParms parms, SLE::ref);
SLE::pointer getAccountRoot (Account const& accountID) const;
SLE::pointer getAccountRoot (const RippleAddress & naAccountID) const;
void updateSkipList ();
void visitAccountItems (
Account const& accountID, std::function<void (SLE::ref)>) const;
bool visitAccountItems (
Account const& accountID,
uint256 const& startAfter, // Entry to start after
std::uint64_t const hint, // Hint which page to start at
unsigned int limit,
std::function <bool (SLE::ref)>) const;
void visitStateItems (std::function<void (SLE::ref)>) const;
// database functions (low-level)
static Ledger::pointer loadByIndex (std::uint32_t ledgerIndex);
static Ledger::pointer loadByHash (uint256 const& ledgerHash);
static uint256 getHashByIndex (std::uint32_t index);
static bool getHashesByIndex (
std::uint32_t index, uint256 & ledgerHash, uint256 & parentHash);
static std::map< std::uint32_t, std::pair<uint256, uint256> >
getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq);
bool pendSaveValidated (bool isSynchronous, bool isCurrent);
// next/prev function
SLE::pointer getSLE (uint256 const& uHash) const; // SLE is mutable
SLE::pointer getSLEi (uint256 const& uHash) const; // SLE is immutable
// VFALCO NOTE These seem to let you walk the list of ledgers
//
uint256 getFirstLedgerIndex () const;
uint256 getLastLedgerIndex () const;
// first node >hash
uint256 getNextLedgerIndex (uint256 const& uHash) const;
// first node >hash, <end
uint256 getNextLedgerIndex (uint256 const& uHash, uint256 const& uEnd) const;
// last node <hash
uint256 getPrevLedgerIndex (uint256 const& uHash) const;
// last node <hash, >begin
uint256 getPrevLedgerIndex (uint256 const& uHash, uint256 const& uBegin) const;
// Ledger hash table function
uint256 getLedgerHash (std::uint32_t ledgerIndex);
using LedgerHashes = std::vector<std::pair<std::uint32_t, uint256>>;
LedgerHashes getLedgerHashes () const;
std::vector<uint256> getLedgerAmendments () const;
// first node >hash, <last
uint256 getNextLedgerIndex (uint256 const& hash,
boost::optional<uint256> const& last = boost::none) const;
std::vector<uint256> getNeededTransactionHashes (
int max, SHAMapSyncFilter* filter) const;
std::vector<uint256> getNeededAccountStateHashes (
int max, SHAMapSyncFilter* filter) const;
//
// Offer functions
//
SLE::pointer getOffer (uint256 const& uIndex) const;
SLE::pointer getOffer (Account const& account, std::uint32_t uSequence) const;
//
// Directory functions
// Directories are doubly linked lists of nodes.
// Given a directory root and and index compute the index of a node.
static void ownerDirDescriber (SLE::ref, bool, Account const& owner);
// Return a node: root or normal
SLE::pointer getDirNode (uint256 const& uNodeIndex) const;
//
// Quality
//
@@ -368,17 +376,6 @@ public:
Currency const& uTakerGetsCurrency, Account const& uTakerGetsIssuer,
const std::uint64_t & uRate);
//
// Ripple functions : credit lines
//
SLE::pointer
getRippleState (uint256 const& uNode) const;
SLE::pointer
getRippleState (
Account const& a, Account const& b, Currency const& currency) const;
std::uint32_t getReferenceFeeUnits() const
{
// Returns the cost of the reference transaction in fee units
@@ -407,23 +404,24 @@ public:
return mReserveIncrement;
}
/** Const version of getHash() which gets the current value without calling
updateHash(). */
uint256 const& getRawHash () const
{
return mHash;
}
bool walkLedger () const;
bool assertSane () const;
bool assertSane ();
// database functions (low-level)
static Ledger::pointer loadByIndex (std::uint32_t ledgerIndex);
static Ledger::pointer loadByHash (uint256 const& ledgerHash);
static uint256 getHashByIndex (std::uint32_t index);
static bool getHashesByIndex (
std::uint32_t index, uint256 & ledgerHash, uint256 & parentHash);
static std::map< std::uint32_t, std::pair<uint256, uint256> >
getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq);
protected:
SLE::pointer getASNode (
LedgerStateParms& parms, uint256 const& nodeID, LedgerEntryType let) const;
// returned SLE is immutable
SLE::pointer getASNodeI (uint256 const& nodeID, LedgerEntryType let) const;
void saveValidatedLedgerAsync(Job&, bool current)
{
saveValidatedLedger(current);
@@ -431,6 +429,12 @@ protected:
bool saveValidatedLedger (bool current);
private:
// ledger close flags
static const std::uint32_t sLCF_NoConsensusTime = 1;
void
updateHash();
// Updates the fees cached in the ledger.
// Safe to call concurrently. We shouldn't be storing
// fees in the Ledger object, they should be a local side-structure
@@ -439,12 +443,12 @@ private:
void deprecatedUpdateCachedFees() const;
// The basic Ledger structure, can be opened, closed, or synching
uint256 mHash; // VFALCO This could be boost::optional<uint256>
uint256 mParentHash;
uint256 mTransHash;
uint256 mAccountHash;
uint256 mHash; // VFALCO This could be boost::optional<uint256>
uint256 mParentHash;
uint256 mTransHash;
uint256 mAccountHash;
std::uint64_t mTotCoins;
std::uint32_t mLedgerSeq;
std::uint32_t seq_;
// when this ledger closed
std::uint32_t mCloseTime;
@@ -481,19 +485,65 @@ private:
std::uint32_t mutable mReserveIncrement = 0;
};
inline LedgerStateParms operator| (
const LedgerStateParms& l1, const LedgerStateParms& l2)
{
return static_cast<LedgerStateParms> (
static_cast<int> (l1) | static_cast<int> (l2));
}
//------------------------------------------------------------------------------
//
// API
//
//------------------------------------------------------------------------------
inline LedgerStateParms operator& (
const LedgerStateParms& l1, const LedgerStateParms& l2)
{
return static_cast<LedgerStateParms> (
static_cast<int> (l1) & static_cast<int> (l2));
}
std::tuple<Ledger::pointer, std::uint32_t, uint256>
loadLedgerHelper(std::string const& sqlSuffix);
/** SLE cache-aware deserialized state SLE fetch.
Effects:
If the key exists, the item is flattened
and added to the SLE cache.
The returned object may not be modified.
@param type An optional LedgerEntryType. If type is
engaged and the SLE's type does not match,
an empty shared_ptr is returned.
@return `empty` if the key is not present
*/
std::shared_ptr<SLE const>
fetch (Ledger const& ledger, uint256 const& key, SLECache& cache,
boost::optional<LedgerEntryType> type = boost::none);
/** Iterate all items in an account's owner directory. */
void
forEachItem (Ledger const& ledger, Account const& id, SLECache& cache,
std::function<void (std::shared_ptr<SLE const> const&)> f);
/** Iterate all items after an item in an owner directory.
@param after The key of the item to start after
@param hint The directory page containing `after`
@param limit The maximum number of items to return
@return `false` if the iteration failed
*/
bool
forEachItemAfter (Ledger const& ledger, Account const& id, SLECache& cache,
uint256 const& after, std::uint64_t const hint, unsigned int limit,
std::function <bool (std::shared_ptr<SLE const> const&)>);
// DEPRECATED
// VFALCO This could return by value
// This should take AccountID parameter
AccountState::pointer
getAccountState (Ledger const& ledger,
RippleAddress const& accountID,
SLECache& cache);
/** Return the hash of a ledger by sequence.
The hash is retrieved by looking up the "skip list"
in the passed ledger. As the skip list is limited
in size, if the requested ledger sequence number is
out of the range of ledgers represented in the skip
list, then boost::none is returned.
@return The hash of the ledger with the
given sequence number or boost::none.
*/
boost::optional<uint256>
hashOfSeq (Ledger& ledger, LedgerIndex seq,
SLECache& cache, beast::Journal journal);
} // ripple

View File

@@ -103,29 +103,53 @@ SLE::pointer LedgerEntrySet::entryCreate (LedgerEntryType letType, uint256 const
return sleNew;
}
SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& index)
SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& key)
{
assert (mLedger);
SLE::pointer sleEntry;
SLE::pointer sle;
if (index.isNonZero ())
// VFALCO Shouldn't be calling this with invalid keys,
// but apparently its happening. Need to track it down.
//assert(key.isNonZero ());
if (key.isNonZero ())
{
LedgerEntryAction action;
sleEntry = getEntry (index, action);
sle = getEntry (key, action);
if (!sleEntry)
if (! sle)
{
assert (action != taaDELETE);
sleEntry = mImmutable ? mLedger->getSLEi (index) : mLedger->getSLE (index);
if (mImmutable)
{
// VFALCO NOTE We'd like all immutable callers to go through
// entryCacheI, then we can avoid calling getSLEi.
sle = mLedger->getSLEi(key);
}
else
{
auto maybe_sle = mLedger->fetch(key, letType);
if (maybe_sle)
sle = std::make_shared<SLE>(
std::move(*maybe_sle));
}
if (sleEntry)
entryCache (sleEntry);
if (sle)
entryCache (sle);
}
else if (action == taaDELETE)
sleEntry.reset ();
{
sle = nullptr;
}
}
return sleEntry;
return sle;
}
std::shared_ptr<SLE const>
LedgerEntrySet::entryCacheI (LedgerEntryType letType, uint256 const& key)
{
return entryCache(letType, key);
}
void LedgerEntrySet::entryCache (SLE::ref sle)
@@ -370,12 +394,16 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
return me->second;
}
SLE::pointer ret = ledger->getSLE (node);
auto sle = ledger->fetch(node);
if (sle)
{
auto p = std::make_shared<SLE>(
std::move(*sle));
newMods.insert (std::make_pair (node, p));
return p;
}
if (ret)
newMods.insert (std::make_pair (node, ret));
return ret;
return {};
}
bool LedgerEntrySet::threadTx (RippleAddress const& threadTo, Ledger::ref ledger,
@@ -418,8 +446,9 @@ bool LedgerEntrySet::threadTx (SLE::ref threadTo, Ledger::ref ledger,
return false;
}
bool LedgerEntrySet::threadOwners (SLE::ref node, Ledger::ref ledger,
NodeToLedgerEntry& newMods)
bool LedgerEntrySet::threadOwners(
std::shared_ptr<SLE const> const& node,
Ledger::ref ledger, NodeToLedgerEntry& newMods)
{
// thread new or modified node to owner or owners
if (node->hasOneOwner ()) // thread to owner's account
@@ -483,7 +512,8 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
if (type == &sfGeneric)
continue;
SLE::pointer origNode = mLedger->getSLEi (it.first);
std::shared_ptr<SLE const> const origNode =
mLedger->getSLEi(it.first);
SLE::pointer curNode = it.second.mEntry;
if ((type == &sfModifiedNode) && (*curNode == *origNode))
@@ -929,6 +959,22 @@ bool LedgerEntrySet::dirFirst (
return LedgerEntrySet::dirNext (uRootIndex, sleNode, uDirEntry, uEntryIndex);
}
// Return the first entry and advance uDirEntry.
// <-- true, if had a next entry.
bool LedgerEntrySet::dirFirst (
uint256 const& uRootIndex, // --> Root of directory.
std::shared_ptr<SLE const>& sleNode, // <-- current node
unsigned int& uDirEntry, // <-- next entry
uint256& uEntryIndex) // <-- The entry, if available. Otherwise, zero.
{
sleNode = entryCacheI (ltDIR_NODE, uRootIndex);
uDirEntry = 0;
assert (sleNode); // Never probe for directories.
return LedgerEntrySet::dirNext (uRootIndex, sleNode, uDirEntry, uEntryIndex);
}
// Return the current entry and advance uDirEntry.
// <-- true, if had a next entry.
bool LedgerEntrySet::dirNext (
@@ -979,6 +1025,57 @@ bool LedgerEntrySet::dirNext (
return true;
}
// Return the current entry and advance uDirEntry.
// <-- true, if had a next entry.
bool LedgerEntrySet::dirNext (
uint256 const& uRootIndex, // --> Root of directory
std::shared_ptr<SLE const>& sleNode, // <-> current node
unsigned int& uDirEntry, // <-> next entry
uint256& uEntryIndex) // <-- The entry, if available. Otherwise, zero.
{
STVector256 const svIndexes = sleNode->getFieldV256 (sfIndexes);
assert (uDirEntry <= svIndexes.size ());
if (uDirEntry >= svIndexes.size ())
{
std::uint64_t const uNodeNext = sleNode->getFieldU64 (sfIndexNext);
if (!uNodeNext)
{
uEntryIndex.zero ();
return false;
}
else
{
auto const sleNext = entryCacheI(
ltDIR_NODE, getDirNodeIndex (uRootIndex, uNodeNext));
uDirEntry = 0;
if (!sleNext)
{ // This should never happen
WriteLog (lsFATAL, LedgerEntrySet)
<< "Corrupt directory: index:"
<< uRootIndex << " next:" << uNodeNext;
return false;
}
sleNode = sleNext;
// TODO(tom): make this iterative.
return dirNext (uRootIndex, sleNode, uDirEntry, uEntryIndex);
}
}
uEntryIndex = svIndexes[uDirEntry++];
WriteLog (lsTRACE, LedgerEntrySet) << "dirNext:" <<
" uDirEntry=" << uDirEntry <<
" uEntryIndex=" << uEntryIndex;
return true;
}
uint256 LedgerEntrySet::getNextLedgerIndex (uint256 const& uHash)
{
// find next node in ledger that isn't deleted by LES

View File

@@ -155,7 +155,10 @@ public:
// higher-level ledger functions
SLE::pointer entryCreate (LedgerEntryType letType, uint256 const& uIndex);
SLE::pointer entryCache (LedgerEntryType letType, uint256 const& uIndex);
SLE::pointer entryCache (LedgerEntryType letType, uint256 const& key);
std::shared_ptr<SLE const>
entryCacheI (LedgerEntryType letType, uint256 const& uIndex);
// Directory functions.
TER dirAdd (
@@ -174,9 +177,16 @@ public:
bool dirFirst (uint256 const& uRootIndex, SLE::pointer& sleNode,
unsigned int & uDirEntry, uint256 & uEntryIndex);
bool dirFirst (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
unsigned int & uDirEntry, uint256 & uEntryIndex);
bool dirNext (uint256 const& uRootIndex, SLE::pointer& sleNode,
unsigned int & uDirEntry, uint256 & uEntryIndex);
bool dirNext (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
unsigned int & uDirEntry, uint256 & uEntryIndex);
bool dirIsEmpty (uint256 const& uDirIndex);
TER dirCount (uint256 const& uDirIndex, std::uint32_t & uCount);
uint256 getNextLedgerIndex (uint256 const& uHash);
@@ -322,8 +332,8 @@ private:
bool threadTx (
SLE::ref threadTo, Ledger::ref ledger, NodeToLedgerEntry& newMods);
bool threadOwners (
SLE::ref node, Ledger::ref ledger, NodeToLedgerEntry& newMods);
bool threadOwners (std::shared_ptr<SLE const> const& node,
Ledger::ref ledger, NodeToLedgerEntry& newMods);
TER rippleSend (
Account const& uSenderID, Account const& uReceiverID,

View File

@@ -33,7 +33,7 @@ namespace ripple {
struct LedgerFill
{
LedgerFill (Ledger const& l,
LedgerFill (Ledger& l,
int o = 0,
RPC::Yield const& y = {},
RPC::YieldStrategy const& ys = {})
@@ -47,7 +47,7 @@ struct LedgerFill
enum Options {
dumpTxrp = 1, dumpState = 2, expand = 4, full = 8, binary = 16};
Ledger const& ledger;
Ledger& ledger;
int options;
RPC::Yield yield;
RPC::YieldStrategy yieldStrategy;
@@ -75,7 +75,7 @@ void fillJson (Object& json, LedgerFill const& fill)
{
using namespace ripple::RPC;
auto const& ledger = fill.ledger;
auto& ledger = fill.ledger;
bool const bFull (fill.options & LedgerFill::full);
bool const bExpand (fill.options & LedgerFill::expand);
@@ -92,11 +92,11 @@ void fillJson (Object& json, LedgerFill const& fill)
json[jss::closed] = true;
// DEPRECATED
json[jss::hash] = to_string (ledger.getRawHash());
json[jss::hash] = to_string (ledger.getHash());
// DEPRECATED
json[jss::totalCoins] = to_string (ledger.getTotalCoins());
json[jss::ledger_hash] = to_string (ledger.getRawHash());
json[jss::ledger_hash] = to_string (ledger.getHash());
json[jss::transaction_hash] = to_string (ledger.getTransHash());
json[jss::account_hash] = to_string (ledger.getAccountHash());
json[jss::accepted] = ledger.isAccepted();

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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.
*/
//==============================================================================
#ifndef RIPPLE_APP_SLECACHE_H_INCLUDED
#define RIPPLE_APP_SLECACHE_H_INCLUDED
#include <ripple/basics/TaggedCache.h>
#include <ripple/protocol/STLedgerEntry.h>
namespace ripple {
/** STLedgerEntry cache.
This maps keys to the deserialized ledger entries,
to improve performance where the same item in
the ledger is accessed often.
*/
using SLECache = TaggedCache <uint256, STLedgerEntry>;
}
#endif

View File

@@ -248,12 +248,14 @@ public:
stopped();
}
// VFALCO TODO This should return boost::optional<uint256>
LedgerHash getLedgerHash(Ledger::pointer ledger, LedgerIndex index)
{
LedgerHash hash;
boost::optional<LedgerHash> hash;
try
{
hash = ledger->getLedgerHash(index);
hash = hashOfSeq(*ledger, index,
getApp().getSLECache(), m_journal);
}
catch (SHAMapMissingNode &)
{
@@ -262,7 +264,7 @@ public:
getApp().getInboundLedgers().acquire (
ledger->getHash(), ledger->getLedgerSeq(), InboundLedger::fcGENERIC);
}
return hash;
return hash ? *hash : zero; // kludge
}
/** Process a single ledger

View File

@@ -635,14 +635,16 @@ public:
void fixMismatch (Ledger::ref ledger)
{
int invalidate = 0;
uint256 hash;
boost::optional<uint256> hash;
for (std::uint32_t lSeq = ledger->getLedgerSeq () - 1; lSeq > 0; --lSeq)
{
if (haveLedger (lSeq))
{
try
{
hash = ledger->getLedgerHash (lSeq);
hash = hashOfSeq(*ledger, lSeq,
getApp().getSLECache(), m_journal);
}
catch (...)
{
@@ -652,12 +654,12 @@ public:
return;
}
if (hash.isNonZero ())
if (hash)
{
// try to close the seam
Ledger::pointer otherLedger = getLedgerBySeq (lSeq);
if (otherLedger && (otherLedger->getHash () == hash))
if (otherLedger && (otherLedger->getHash () == *hash))
{
// we closed the seam
CondLog (invalidate != 0, lsWARNING, LedgerMaster) <<
@@ -670,6 +672,7 @@ public:
clearLedger (lSeq);
++invalidate;
}
}
// all prior ledgers invalidated
CondLog (invalidate != 0, lsWARNING, LedgerMaster) << "All " <<
@@ -963,24 +966,24 @@ public:
WriteLog (lsTRACE, LedgerMaster) << "advanceThread>";
}
// VFALCO NOTE This should return boost::optional<uint256>
LedgerHash getLedgerHashForHistory (LedgerIndex index)
{
// Try to get the hash of a ledger we need to fetch for history
uint256 ret;
boost::optional<LedgerHash> ret;
if (mHistLedger && (mHistLedger->getLedgerSeq() >= index))
{
ret = mHistLedger->getLedgerHash (index);
if (ret.isZero())
ret = hashOfSeq(*mHistLedger, index,
getApp().getSLECache(), m_journal);
if (! ret)
ret = walkHashBySeq (index, mHistLedger);
}
if (ret.isZero ())
{
ret = walkHashBySeq (index);
}
return ret;
if (! ret)
ret = walkHashBySeq (index);
return *ret;
}
// Try to publish ledgers, acquire missing ledgers
@@ -1160,31 +1163,35 @@ public:
WriteLog (lsTRACE, LedgerMaster) << "Trying to fetch/publish valid ledger " << seq;
Ledger::pointer ledger;
uint256 hash = valLedger->getLedgerHash (seq); // This can throw
// This can throw
auto hash = hashOfSeq(*valLedger, seq,
getApp().getSLECache(), m_journal);
// VFALCO TODO Restructure this code so that zero is not used
if (! hash)
hash = zero; // kludge
if (seq == valSeq)
{ // We need to publish the ledger we just fully validated
{
// We need to publish the ledger we just fully validated
ledger = valLedger;
}
else if (hash->isZero())
{
WriteLog (lsFATAL, LedgerMaster) << "Ledger: " << valSeq << " does not have hash for " << seq;
assert (false);
}
else
{
if (hash.isZero ())
{
WriteLog (lsFATAL, LedgerMaster) << "Ledger: " << valSeq << " does not have hash for " << seq;
assert (false);
}
ledger = mLedgerHistory.getLedgerByHash (hash);
ledger = mLedgerHistory.getLedgerByHash (*hash);
}
// Can we try to acquire the ledger we need?
if (! ledger && (++acqCount < 4))
{ // We can try to acquire the ledger we need
ledger =
getApp().getInboundLedgers ().acquire (hash, seq, InboundLedger::fcGENERIC);
}
ledger = getApp().getInboundLedgers ().acquire(
*hash, seq, InboundLedger::fcGENERIC);
// Did we acquire the next ledger we need to publish?
if (ledger && (ledger->getLedgerSeq() == pubSeq))
{ // We acquired the next ledger we need to publish
{
ledger->setValidated();
ret.push_back (ledger);
++pubSeq;
@@ -1217,33 +1224,41 @@ public:
}
// Return the hash of the valid ledger with a particular sequence, given a subsequent ledger known valid
// VFALCO NOTE This should return boost::optional<uint256>
uint256 getLedgerHash(std::uint32_t desiredSeq, Ledger::ref knownGoodLedger)
{
assert(desiredSeq < knownGoodLedger->getLedgerSeq());
uint256 hash = knownGoodLedger->getLedgerHash(desiredSeq);
auto hash = hashOfSeq(*knownGoodLedger, desiredSeq,
getApp().getSLECache(), m_journal);
// Not directly in the given ledger
if (hash.isZero ())
if (! hash)
{
std::uint32_t seq = (desiredSeq + 255) % 256;
assert(seq < desiredSeq);
uint256 i = knownGoodLedger->getLedgerHash(seq);
if (i.isNonZero())
hash = hashOfSeq(*knownGoodLedger,
seq, getApp().getSLECache(), m_journal);
if (hash)
{
Ledger::pointer l = getLedgerByHash(i);
auto l = getLedgerByHash(*hash);
if (l)
{
hash = l->getLedgerHash(desiredSeq);
assert (hash.isNonZero());
hash = hashOfSeq(*l, desiredSeq,
getApp().getSLECache(), m_journal);
assert (hash);
}
}
else
{
assert(false);
}
}
return hash;
// VFALCO NOTE This shouldn't be needed, but
// preserves original behavior.
return hash ? *hash : zero; // kludge
}
void updatePaths (Job& job)
@@ -1401,6 +1416,7 @@ public:
return Ledger::getHashByIndex (index);
}
// VFALCO NOTE This should return boost::optional<uint256>
uint256 walkHashBySeq (std::uint32_t index)
{
uint256 ledgerHash;
@@ -1419,37 +1435,41 @@ public:
from the reference ledger or any prior ledger are not present
in the node store.
*/
// VFALCO NOTE This should return boost::optional<uint256>
uint256 walkHashBySeq (std::uint32_t index, Ledger::ref referenceLedger)
{
uint256 ledgerHash;
if (!referenceLedger || (referenceLedger->getLedgerSeq() < index))
return ledgerHash; // Nothing we can do. No validated ledger.
{
// Nothing we can do. No validated ledger.
return zero;
}
// See if the hash for the ledger we need is in the reference ledger
ledgerHash = referenceLedger->getLedgerHash (index);
if (ledgerHash.isZero())
{
// No, Try to get another ledger that might have the hash we need
// Compute the index and hash of a ledger that will have the hash we need
LedgerIndex refIndex = (index + 255) & (~255);
LedgerHash refHash = referenceLedger->getLedgerHash (refIndex);
auto ledgerHash = hashOfSeq(*referenceLedger, index,
getApp().getSLECache(), m_journal);
if (ledgerHash)
return *ledgerHash;
bool const nonzero (refHash.isNonZero ());
assert (nonzero);
if (nonzero)
// No, Try to get another ledger that might have the hash we need
// Compute the index and hash of a ledger that will have the hash we need
LedgerIndex refIndex = (index + 255) & (~255);
auto const refHash = hashOfSeq(*referenceLedger, refIndex,
getApp().getSLECache(), m_journal);
assert(refHash);
if (refHash)
{
// We found the hash and sequence of a better reference ledger
auto const ledger =
getApp().getInboundLedgers().acquire (
*refHash, refIndex, InboundLedger::fcGENERIC);
if (ledger)
{
// We found the hash and sequence of a better reference ledger
Ledger::pointer ledger =
getApp().getInboundLedgers().acquire (
refHash, refIndex, InboundLedger::fcGENERIC);
if (ledger)
{
ledgerHash = ledger->getLedgerHash (index);
assert (ledgerHash.isNonZero());
}
ledgerHash = hashOfSeq(*ledger, index,
getApp().getSLECache(), m_journal);
assert (ledgerHash);
}
}
return ledgerHash;
return ledgerHash ? *ledgerHash : zero; // kludge
}
Ledger::pointer getLedgerBySeq (std::uint32_t index)
@@ -1465,9 +1485,10 @@ public:
try
{
uint256 const& hash = valid->getLedgerHash (index);
if (hash.isNonZero())
return mLedgerHistory.getLedgerByHash (hash);
auto const hash = hashOfSeq(*valid, index,
getApp().getSLECache(), m_journal);
if (hash)
return mLedgerHistory.getLedgerByHash (*hash);
}
catch (...)
{

View File

@@ -18,10 +18,10 @@
//==============================================================================
#include <ripple/app/ledger/tests/common_ledger.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/rpc/impl/RipplePathFind.h>
#include <ripple/json/json_writer.h>
@@ -143,7 +143,7 @@ createGenesisLedger(std::uint64_t start_amount_drops, TestAccount const& master)
initializePathfinding();
Ledger::pointer ledger = std::make_shared<Ledger>(master.pk,
start_amount_drops);
ledger->updateHash();
ledger->getHash(); // updates the hash
ledger->setClosed();
if (!ledger->assertSane())
throw std::runtime_error(
@@ -488,10 +488,10 @@ Json::Value findPath(Ledger::pointer ledger, TestAccount const& src,
return result.second;
}
SLE::pointer
std::shared_ptr<SLE const>
getLedgerEntryRippleState(Ledger::pointer ledger,
TestAccount const& account1, TestAccount const& account2,
Currency currency)
Currency currency)
{
auto uNodeIndex = getRippleStateIndex(
account1.pk.getAccountID(), account2.pk.getAccountID(),
@@ -501,14 +501,15 @@ getLedgerEntryRippleState(Ledger::pointer ledger,
throw std::runtime_error(
"!uNodeIndex.isNonZero()");
return ledger->getSLEi(uNodeIndex);
return fetch(*ledger, uNodeIndex,
getApp().getSLECache());
}
void
verifyBalance(Ledger::pointer ledger, TestAccount const& account,
Amount const& amount)
{
auto sle = getLedgerEntryRippleState(ledger, account,
auto const sle = getLedgerEntryRippleState(ledger, account,
amount.getIssuer(), amount.getCurrency());
if (!sle)
throw std::runtime_error(

View File

@@ -26,6 +26,7 @@
#include <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/ledger/OrderBookDB.h>
#include <ripple/app/ledger/PendingSaves.h>
#include <ripple/app/main/CollectorManager.h>
@@ -57,6 +58,7 @@
#include <ripple/nodestore/DummyScheduler.h>
#include <ripple/nodestore/Manager.h>
#include <ripple/overlay/make_Overlay.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/rpc/Manager.h>
#include <ripple/server/make_ServerHandler.h>
@@ -1041,6 +1043,7 @@ public:
private:
void updateTables ();
void startNewLedger ();
Ledger::pointer getLastFullLedger();
bool loadOldLedger (
std::string const& ledgerID, bool replay, bool isFilename);
@@ -1062,10 +1065,10 @@ void ApplicationImp::startNewLedger ()
{
Ledger::pointer firstLedger = std::make_shared<Ledger> (rootAddress, SYSTEM_CURRENCY_START);
assert (firstLedger->getAccountState (rootAddress));
assert (firstLedger->exists(getAccountRootIndex(rootAddress.getAccountID())));
// TODO(david): Add any default amendments
// TODO(david): Set default fee/reserve
firstLedger->updateHash ();
firstLedger->getHash(); // updates the hash
firstLedger->setClosed ();
firstLedger->setAccepted ();
m_ledgerMaster->pushLedger (firstLedger);
@@ -1074,11 +1077,58 @@ void ApplicationImp::startNewLedger ()
secondLedger->setClosed ();
secondLedger->setAccepted ();
m_ledgerMaster->pushLedger (secondLedger, std::make_shared<Ledger> (true, std::ref (*secondLedger)));
assert (secondLedger->getAccountState (rootAddress));
assert (secondLedger->exists(getAccountRootIndex(rootAddress.getAccountID())));
m_networkOPs->setLastCloseTime (secondLedger->getCloseTimeNC ());
}
}
Ledger::pointer
ApplicationImp::getLastFullLedger()
{
try
{
Ledger::pointer ledger;
std::uint32_t ledgerSeq;
uint256 ledgerHash;
std::tie (ledger, ledgerSeq, ledgerHash) =
loadLedgerHelper ("order by LedgerSeq desc limit 1");
if (!ledger)
return ledger;
ledger->setClosed ();
if (getApp().getOPs ().haveLedger (ledgerSeq))
{
ledger->setAccepted ();
ledger->setValidated ();
}
if (ledger->getHash () != ledgerHash)
{
if (ShouldLog (lsERROR, Ledger))
{
WriteLog (lsERROR, Ledger) << "Failed on ledger";
Json::Value p;
addJson (p, {*ledger, LedgerFill::full});
WriteLog (lsERROR, Ledger) << p;
}
assert (false);
return Ledger::pointer ();
}
WriteLog (lsTRACE, Ledger) << "Loaded ledger: " << ledgerHash;
return ledger;
}
catch (SHAMapMissingNode& sn)
{
WriteLog (lsWARNING, Ledger)
<< "Database contains ledger with missing nodes: " << sn;
return Ledger::pointer ();
}
}
bool ApplicationImp::loadOldLedger (
std::string const& ledgerID, bool replay, bool isFileName)
{
@@ -1185,7 +1235,9 @@ bool ApplicationImp::loadOldLedger (
}
}
else if (ledgerID.empty () || (ledgerID == "latest"))
loadLedger = Ledger::getLastFullLedger ();
{
loadLedger = getLastFullLedger ();
}
else if (ledgerID.length () == 64)
{
// by hash

View File

@@ -23,10 +23,11 @@
#include <ripple/shamap/FullBelowCache.h>
#include <ripple/shamap/TreeNodeCache.h>
#include <ripple/basics/TaggedCache.h>
#include <ripple/app/ledger/SLECache.h>
#include <beast/utility/PropertyStream.h>
#include <beast/cxx14/memory.h> // <memory>
#include <mutex>
namespace boost { namespace asio { class io_service; } }
namespace ripple {
@@ -65,7 +66,6 @@ class DatabaseCon;
class SHAMapStore;
using NodeCache = TaggedCache <uint256, Blob>;
using SLECache = TaggedCache <uint256, STLedgerEntry>;
class Application : public beast::PropertyStream::Source
{

View File

@@ -29,25 +29,11 @@
namespace ripple {
AccountState::AccountState (RippleAddress const& naAccountID)
: mAccountID (naAccountID)
, mValid (false)
AccountState::AccountState (std::shared_ptr<SLE const> sle,
RippleAddress const& naAccountID)
: mLedgerEntry (sle)
{
if (naAccountID.isValid ())
{
mValid = true;
mLedgerEntry = std::make_shared <STLedgerEntry> (
ltACCOUNT_ROOT, getAccountRootIndex (naAccountID));
mLedgerEntry->setFieldAccount (sfAccount, naAccountID.getAccountID ());
}
}
AccountState::AccountState (SLE::ref ledgerEntry, RippleAddress const& naAccountID) :
mAccountID (naAccountID), mLedgerEntry (ledgerEntry), mValid (false)
{
if (!mLedgerEntry)
if (! mLedgerEntry)
return;
if (mLedgerEntry->getType () != ltACCOUNT_ROOT)
@@ -84,11 +70,4 @@ void AccountState::addJson (Json::Value& val)
}
}
void AccountState::dump ()
{
Json::Value j (Json::objectValue);
addJson (j);
WriteLog (lsINFO, Ledger) << j;
}
} // ripple

View File

@@ -28,70 +28,35 @@
namespace ripple {
//
// Provide abstract access to an account's state, such that access to the serialized format is hidden.
// Provide abstract access to an account's state, such that
// access to the serialized format is hidden.
//
// VFALCO TODO Remove this class, its redundant and hardly used
class AccountState
{
public:
// VFALCO TODO Figure out if we need this to be shared
using pointer = std::shared_ptr<AccountState>;
public:
// For new accounts
explicit AccountState (RippleAddress const& naAccountID);
// For accounts in a ledger
AccountState (SLE::ref ledgerEntry, RippleAddress const& naAccountI);
AccountState (std::shared_ptr<SLE const> sle,
RippleAddress const& naAccountI);
bool haveAuthorizedKey ()
{
return mLedgerEntry->isFieldPresent (sfRegularKey);
}
RippleAddress getAuthorizedKey ()
{
return mLedgerEntry->getFieldAccount (sfRegularKey);
}
STAmount getBalance () const
{
return mLedgerEntry->getFieldAmount (sfBalance);
}
std::uint32_t getSeq () const
{
return mLedgerEntry->getFieldU32 (sfSequence);
}
STLedgerEntry::pointer getSLE ()
{
return mLedgerEntry;
}
STLedgerEntry const& peekSLE () const
SLE const&
sle() const
{
return *mLedgerEntry;
}
STLedgerEntry& peekSLE ()
{
return *mLedgerEntry;
}
Blob getRaw () const;
void addJson (Json::Value& value);
void dump ();
private:
// VFALCO TODO Remove this
static std::string createGravatarUrl (uint128 uEmailHash);
private:
RippleAddress const mAccountID;
RippleAddress mAuthorizedKey;
STLedgerEntry::pointer mLedgerEntry;
bool mValid;
bool mValid = false;
std::shared_ptr<SLE const> mLedgerEntry;
};
} // ripple

View File

@@ -245,13 +245,6 @@ public:
std::uint32_t startLedgerSeq, std::uint32_t endLedgerSeq,
int maxTransactions) override;
//
// Account functions.
//
AccountState::pointer getAccountState (
Ledger::ref lrLedger, RippleAddress const& accountID) override;
//
// Directory functions.
//
@@ -1082,16 +1075,6 @@ int NetworkOPsImp::findTransactionsByDestination (
return 0;
}
//
// Account functions
//
AccountState::pointer NetworkOPsImp::getAccountState (
Ledger::ref lrLedger, RippleAddress const& accountID)
{
return lrLedger->getAccountState (accountID);
}
//
// Directory functions
//
@@ -1104,7 +1087,8 @@ STVector256 NetworkOPsImp::getDirNodeInfo (
std::uint64_t& uNodeNext)
{
STVector256 svIndexes;
SLE::pointer sleNode = lrLedger->getDirNode (uNodeIndex);
auto const sleNode = fetch(*lrLedger, uNodeIndex,
getApp().getSLECache(), ltDIR_NODE);
if (sleNode)
{
@@ -1149,8 +1133,8 @@ Json::Value NetworkOPsImp::getOwnerInfo (
{
Json::Value jvObjects (Json::objectValue);
auto uRootIndex = getOwnerDirIndex (naAccount.getAccountID ());
auto sleNode = lpLedger->getDirNode (uRootIndex);
auto sleNode = fetch(*lpLedger, uRootIndex,
getApp().getSLECache(), ltDIR_NODE);
if (sleNode)
{
std::uint64_t uNodeDir;
@@ -1159,7 +1143,8 @@ Json::Value NetworkOPsImp::getOwnerInfo (
{
for (auto const& uDirEntry : sleNode->getFieldV256 (sfIndexes))
{
auto sleCur = lpLedger->getSLEi (uDirEntry);
auto sleCur = fetch(*lpLedger, uDirEntry,
getApp().getSLECache());
switch (sleCur->getType ())
{
@@ -1192,8 +1177,9 @@ Json::Value NetworkOPsImp::getOwnerInfo (
if (uNodeDir)
{
sleNode = lpLedger->getDirNode (
getDirNodeIndex (uRootIndex, uNodeDir));
sleNode = fetch(*lpLedger, getDirNodeIndex(
uRootIndex, uNodeDir), getApp().getSLECache(),
ltDIR_NODE);
assert (sleNode);
}
}

View File

@@ -168,14 +168,6 @@ public:
RippleAddress const& destinationAccount, std::uint32_t startLedgerSeq,
std::uint32_t endLedgerSeq, int maxTransactions) = 0;
//--------------------------------------------------------------------------
//
// Account functions
//
virtual AccountState::pointer getAccountState (Ledger::ref lrLedger,
RippleAddress const& accountID) = 0;
//--------------------------------------------------------------------------
//
// Directory functions

View File

@@ -149,8 +149,9 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
if (bValid)
{
auto asSrc = getApp().getOPs ().getAccountState (
crCache->getLedger(), raSrcAccount);
auto asSrc = getAccountState(
*crCache->getLedger(), raSrcAccount,
getApp().getSLECache());
if (!asSrc)
{
@@ -160,8 +161,8 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
}
else
{
auto asDst = getApp().getOPs ().getAccountState (
lrLedger, raDstAccount);
auto asDst = getAccountState(*lrLedger,
raDstAccount, getApp().getSLECache());
Json::Value& jvDestCur =
(jvStatus[jss::destination_currencies] = Json::arrayValue);
@@ -187,7 +188,7 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
else
{
bool const disallowXRP (
asDst->peekSLE ().getFlags() & lsfDisallowXRP);
asDst->sle().getFlags() & lsfDisallowXRP);
auto usDestCurrID = accountDestCurrencies (
raDstAccount, crCache, !disallowXRP);
@@ -196,7 +197,7 @@ bool PathRequest::isValid (RippleLineCache::ref crCache)
jvDestCur.append (to_string (currency));
jvStatus["destination_tag"] =
(asDst->peekSLE ().getFlags () & lsfRequireDestTag)
(asDst->sle().getFlags () & lsfRequireDestTag)
!= 0;
}
}

View File

@@ -271,7 +271,7 @@ bool Pathfinder::findPaths (int searchLevel)
bool bSrcXrp = isXRP (mSrcCurrency);
bool bDstXrp = isXRP (mDstAmount.getCurrency());
if (!mLedger->getSLEi (getAccountRootIndex (mSrcAccount)))
if (! mLedger->exists (getAccountRootIndex (mSrcAccount)))
{
// We can't even start without a source account.
WriteLog (lsDEBUG, Pathfinder) << "invalid source account";
@@ -279,14 +279,14 @@ bool Pathfinder::findPaths (int searchLevel)
}
if ((mEffectiveDst != mDstAccount) &&
! mLedger->getSLEi (getAccountRootIndex (mEffectiveDst)))
! mLedger->exists (getAccountRootIndex (mEffectiveDst)))
{
WriteLog (lsDEBUG, Pathfinder)
<< "Non-existent gateway";
return false;
}
if (!mLedger->getSLEi (getAccountRootIndex (mDstAccount)))
if (! mLedger->exists (getAccountRootIndex (mDstAccount)))
{
// Can't find the destination account - we must be funding a new
// account.
@@ -703,7 +703,8 @@ int Pathfinder::getPathsOut (
if (!it.second)
return it.first->second;
auto sleAccount = mLedger->getSLEi (getAccountRootIndex (account));
auto sleAccount = fetch(*mLedger, getAccountRootIndex (account),
getApp().getSLECache());
if (!sleAccount)
return 0;
@@ -839,8 +840,9 @@ bool Pathfinder::isNoRipple (
Account const& toAccount,
Currency const& currency)
{
auto sleRipple = mLedger->getSLEi (
getRippleStateIndex (toAccount, fromAccount, currency));
auto sleRipple = fetch (*mLedger,
getRippleStateIndex (toAccount, fromAccount, currency),
getApp().getSLECache());
auto const flag ((toAccount > fromAccount)
? lsfHighNoRipple : lsfLowNoRipple);
@@ -918,7 +920,9 @@ void Pathfinder::addLink (
else
{
// search for accounts to add
auto sleEnd = mLedger->getSLEi(getAccountRootIndex (uEndAccount));
auto const sleEnd = fetch(
*mLedger, getAccountRootIndex (uEndAccount),
getApp().getSLECache());
if (sleEnd)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/paths/RippleState.h>
#include <ripple/protocol/STAmount.h>
#include <cstdint>
@@ -25,25 +26,27 @@
namespace ripple {
RippleState::pointer RippleState::makeItem (
Account const& accountID, STLedgerEntry::ref ledgerEntry)
RippleState::pointer
RippleState::makeItem (
Account const& accountID,
std::shared_ptr<SLE const> sle)
{
// VFALCO Does this ever happen in practice?
if (!ledgerEntry || ledgerEntry->getType () != ltRIPPLE_STATE)
return pointer ();
return pointer (new RippleState (ledgerEntry, accountID));
if (! sle || sle->getType () != ltRIPPLE_STATE)
return {};
return std::make_shared<RippleState>(
std::move(sle), accountID);
}
RippleState::RippleState (
STLedgerEntry::ref ledgerEntry,
std::shared_ptr<SLE const>&& sle,
Account const& viewAccount)
: mLedgerEntry (ledgerEntry)
, mLowLimit (ledgerEntry->getFieldAmount (sfLowLimit))
, mHighLimit (ledgerEntry->getFieldAmount (sfHighLimit))
: mLedgerEntry (std::move(sle))
, mLowLimit (mLedgerEntry->getFieldAmount (sfLowLimit))
, mHighLimit (mLedgerEntry->getFieldAmount (sfHighLimit))
, mLowID (mLowLimit.getIssuer ())
, mHighID (mHighLimit.getIssuer ())
, mBalance (ledgerEntry->getFieldAmount (sfBalance))
, mBalance (mLedgerEntry->getFieldAmount (sfBalance))
{
mFlags = mLedgerEntry->getFieldU32 (sfFlags);
@@ -73,12 +76,11 @@ getRippleStateItems (
Ledger::ref ledger)
{
std::vector <RippleState::pointer> items;
ledger->visitAccountItems (accountID,
[&items,&accountID](SLE::ref sleCur)
forEachItem(*ledger, accountID, getApp().getSLECache(),
[&items,&accountID](
std::shared_ptr<SLE const> const&sleCur)
{
auto ret = RippleState::makeItem (accountID, sleCur);
if (ret)
items.push_back (ret);
});

View File

@@ -22,34 +22,47 @@
#include <ripple/app/ledger/LedgerEntrySet.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <cstdint>
#include <beast/cxx14/memory.h> // <memory>
namespace ripple {
//
// A ripple line's state.
// - Isolate ledger entry format.
//
/** Wraps a trust line SLE for convenience.
The complication of trust lines is that there is a
"low" account and a "high" account. This wraps the
SLE and expresses its data from the perspective of
a chosen account on the line.
*/
// VFALCO TODO Rename to TrustLine
class RippleState
{
public:
// VFALCO Why is this shared_ptr?
using pointer = std::shared_ptr <RippleState>;
public:
RippleState () = delete;
RippleState() = delete;
virtual ~RippleState () { }
virtual ~RippleState() = default;
static RippleState::pointer makeItem (
Account const& accountID, STLedgerEntry::ref ledgerEntry);
static RippleState::pointer makeItem(
Account const& accountID,
std::shared_ptr<SLE const> sle);
LedgerEntryType getType ()
// Must be public, for make_shared
RippleState (std::shared_ptr<SLE const>&& sle,
Account const& viewAccount);
/** Returns the state map key for the ledger entry. */
uint256
key() const
{
return ltRIPPLE_STATE;
return mLedgerEntry->getIndex();
}
// VFALCO Take off the "get" from each function name
Account const& getAccountID () const
{
return mViewLowest ? mLowID : mHighID;
@@ -118,32 +131,10 @@ public:
return ((std::uint32_t) (mViewLowest ? mLowQualityOut : mHighQualityOut));
}
STLedgerEntry::pointer getSLE ()
{
return mLedgerEntry;
}
const STLedgerEntry& peekSLE () const
{
return *mLedgerEntry;
}
STLedgerEntry& peekSLE ()
{
return *mLedgerEntry;
}
Json::Value getJson (int);
Blob getRaw () const;
private:
RippleState (
STLedgerEntry::ref ledgerEntry,
Account const& viewAccount);
private:
STLedgerEntry::pointer mLedgerEntry;
std::shared_ptr<SLE const> mLedgerEntry;
bool mViewLowest;

View File

@@ -45,10 +45,9 @@ AccountInfo::balance(
return STAmount(issue, 0, 0);
if (isXRP(issue))
return root_->getFieldAmount(sfBalance);
auto amount = ledger_->getRippleState(
auto amount = ledger_->fetch(getRippleStateIndex(
account_, issue.account,
issue.currency)->getFieldAmount(
sfBalance);
issue.currency))->getFieldAmount(sfBalance);
amount.setIssuer(issue.account);
if (account_.id() > issue.account)
amount.negate();
@@ -204,7 +203,7 @@ Env::autofill (JTx& jt)
auto const account =
lookup(jv[jss::Account].asString());
auto const ar =
ledger->getAccountRoot(account);
ledger->fetch(getAccountRootIndex(account));
if (ar->isFieldPresent(sfRegularKey))
jtx::sign(jv, lookup(
ar->getFieldAccount160(sfRegularKey)));

View File

@@ -25,6 +25,7 @@
#include <ripple/app/ledger/Ledger.h>
#include <ripple/json/json_value.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STAmount.h>
@@ -45,15 +46,15 @@ class AccountInfo
private:
Account account_;
std::shared_ptr<Ledger> ledger_;
std::shared_ptr<STLedgerEntry> root_;
boost::optional<SLE const> root_;
public:
AccountInfo(Account const& account,
std::shared_ptr<Ledger> ledger)
: account_(account)
, ledger_(std::move(ledger))
, root_(ledger_->getAccountRoot(
account.id()))
, root_(ledger_->fetch(
getAccountRootIndex(account.id())))
{
}

View File

@@ -170,8 +170,9 @@ fill_seq (Json::Value& jv,
return;
RippleAddress ra;
ra.setAccountID(jv[jss::Account].asString());
auto const ar = ledger.getAccountRoot(
ra.getAccountID());
auto const ar = ledger.fetch(
getAccountRootIndex(ra.getAccountID()));
jv[jss::Sequence] =
ar->getFieldU32(sfSequence);
}

View File

@@ -20,6 +20,7 @@
#include <BeastConfig.h>
#include <ripple/app/tx/LocalTxs.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/protocol/Indexes.h>
/*
This code prevents scenarios like the following:
@@ -120,21 +121,16 @@ public:
bool can_remove (LocalTx& txn, Ledger::ref ledger)
{
if (txn.isExpired (ledger->getLedgerSeq ()))
return true;
if (ledger->hasTransaction (txn.getID ()))
return true;
SLE::pointer sle = ledger->getAccountRoot (txn.getAccount ());
if (!sle)
auto const sle = ledger->fetch(
getAccountRootIndex(txn.getAccount()));
if (! sle)
return false;
if (sle->getFieldU32 (sfSequence) > txn.getSeq ())
return true;
return false;
}

View File

@@ -36,6 +36,9 @@ void TransactionEngine::txnWrite ()
// Write back the account states
for (auto& it : mNodes)
{
// VFALCO TODO rvalue move the mEntry, make
// sure the mNodes is not used after
// this function is called.
SLE::ref sleEntry = it.second.mEntry;
switch (it.second.mAction)
@@ -49,11 +52,10 @@ void TransactionEngine::txnWrite ()
case taaCREATE:
{
// VFALCO Is this logging necessary anymore?
WriteLog (lsDEBUG, TransactionEngine) <<
"applyTransaction: taaCREATE: " << sleEntry->getText ();
if (mLedger->writeBack (lepCREATE, sleEntry) & lepERROR)
assert (false);
mLedger->insert(*sleEntry);
}
break;
@@ -61,9 +63,7 @@ void TransactionEngine::txnWrite ()
{
WriteLog (lsDEBUG, TransactionEngine) <<
"applyTransaction: taaMODIFY: " << sleEntry->getText ();
if (mLedger->writeBack (lepNONE, sleEntry) & lepERROR)
assert (false);
mLedger->replace(*sleEntry);
}
break;
@@ -71,9 +71,7 @@ void TransactionEngine::txnWrite ()
{
WriteLog (lsDEBUG, TransactionEngine) <<
"applyTransaction: taaDELETE: " << sleEntry->getText ();
if (!mLedger->peekAccountStateMap ()->delItem (it.first))
assert (false);
mLedger->erase(it.first);
}
break;
}

View File

@@ -1462,12 +1462,12 @@ class MultiSign_test : public beast::unit_test::suite
}
// Verify that alice has an offer.
{
std::vector<SLE::pointer> offers =
auto offers =
getOffersOnAccount (ledger, alice);
expect (offers.size() == 1);
if (! offers.empty())
{
SLE::pointer const& offer = offers[0];
auto const& offer = offers[0];
expect (takerGets == offer->getFieldAmount(sfTakerGets));
expect (takerPays == offer->getFieldAmount(sfTakerPays));
offerSeq = offer->getFieldU32 (sfSequence);
@@ -1486,7 +1486,7 @@ class MultiSign_test : public beast::unit_test::suite
}
// Make sure alice's offer is really gone from the ledger.
{
std::vector<SLE::pointer> offers =
auto offers =
getOffersOnAccount (ledger, alice);
expect (offers.empty() == true);
}
@@ -1558,7 +1558,7 @@ class MultiSign_test : public beast::unit_test::suite
}
// Make sure Alice has the ticket.
{
std::vector<SLE::pointer> tickets =
auto
getTicketsOnAccount (ledger, alice);
expect (tickets.size() == 1);
if (! tickets.empty())
@@ -1583,7 +1583,7 @@ class MultiSign_test : public beast::unit_test::suite
}
// Make sure the ticket is gone.
{
std::vector<SLE::pointer> tickets =
auto tickets =
getTicketsOnAccount (ledger, alice);
expect (tickets.size() == 0);
}

View File

@@ -16,6 +16,7 @@
//==============================================================================
#include <ripple/app/tx/tests/common_transactor.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/app/ledger/tests/common_ledger.h>
@@ -136,7 +137,9 @@ void TestLedger::applyTecTransaction (STTx const& tx, TER err, bool check)
AccountState::pointer
TestLedger::getAccountState (UserAccount const& acct) const
{
return lastClosedLedger_->getAccountState (acct.acctPublicKey ());
return ripple::getAccountState(
*lastClosedLedger_, acct.acctPublicKey(),
getApp().getSLECache());
}
//------------------------------------------------------------------------------
@@ -362,12 +365,13 @@ void payInDrops (TestLedger& ledger,
std::uint64_t getNativeBalance(TestLedger& ledger, UserAccount& acct)
{
return ledger.getAccountState(acct)->getBalance().mantissa ();
return ledger.getAccountState(acct)->sle().getFieldAmount(
sfBalance).mantissa();
}
std::uint32_t getOwnerCount(TestLedger& ledger, UserAccount& acct)
{
return ledger.getAccountState(acct)->getSLE()->getFieldU32 (sfOwnerCount);
return ledger.getAccountState(acct)->sle().getFieldU32 (sfOwnerCount);
}
std::vector<RippleState::pointer> getRippleStates (
@@ -375,9 +379,9 @@ std::vector<RippleState::pointer> getRippleStates (
{
std::vector <RippleState::pointer> states;
ledger.openLedger()->visitAccountItems (
acct.getID(),
[&states, &acct, &peer](SLE::ref sleCur)
forEachItem(*ledger.openLedger(), acct.getID(), getApp().getSLECache(),
[&states, &acct, &peer](
std::shared_ptr<SLE const> const& sleCur)
{
// See whether this SLE is a lt_RIPPLE_STATE
if (!sleCur || sleCur->getType () != ltRIPPLE_STATE)
@@ -394,14 +398,14 @@ std::vector<RippleState::pointer> getRippleStates (
return states;
}
std::vector <SLE::pointer>
std::vector <std::shared_ptr<SLE const>>
getOffersOnAccount (TestLedger& ledger, UserAccount const& acct)
{
std::vector <SLE::pointer> offers;
std::vector <std::shared_ptr<SLE const>> offers;
ledger.openLedger()->visitAccountItems (
acct.getID(),
[&offers, &acct](SLE::ref sleCur)
forEachItem(*ledger.openLedger(), acct.getID(), getApp().getSLECache(),
[&offers, &acct](
std::shared_ptr<SLE const> const& sleCur)
{
// If sleCur is an ltOFFER save it.
if (sleCur && sleCur->getType () == ltOFFER)
@@ -410,14 +414,14 @@ getOffersOnAccount (TestLedger& ledger, UserAccount const& acct)
return offers;
}
std::vector <SLE::pointer>
std::vector <std::shared_ptr<SLE const>>
getTicketsOnAccount (TestLedger& ledger, UserAccount const& acct)
{
std::vector <SLE::pointer> offers;
std::vector <std::shared_ptr<SLE const>> offers;
ledger.openLedger()->visitAccountItems (
acct.getID(),
[&offers, &acct](SLE::ref sleCur)
forEachItem(*ledger.openLedger(), acct.getID(), getApp().getSLECache(),
[&offers, &acct](
std::shared_ptr<SLE const> const& sleCur)
{
// If sleCur is an ltTICKET save it.
if (sleCur && sleCur->getType () == ltTICKET)

View File

@@ -128,6 +128,8 @@ public:
void applyTecTransaction (STTx const& tx, TER err, bool check = true);
// Return the AccountState for a UserAccount
// VFALCO This function is not necessary, just expose
// the ledger data member and use the free function.
AccountState::pointer getAccountState (UserAccount const& acct) const;
// Return the current open ledger.
@@ -347,11 +349,11 @@ std::vector<RippleState::pointer> getRippleStates (
TestLedger& ledger, UserAccount const& from, UserAccount const& peer);
// Get all Offers on an account.
std::vector <SLE::pointer>
std::vector <std::shared_ptr<SLE const>>
getOffersOnAccount (TestLedger& ledger, UserAccount const& acct);
// Get all Tickets on an account.
std::vector <SLE::pointer>
std::vector <std::shared_ptr<SLE const>>
getTicketsOnAccount (TestLedger& ledger, UserAccount const& acct);
} // test

View File

@@ -123,7 +123,15 @@ private:
}
public:
base_uint () { *this = beast::zero; }
base_uint()
{
*this = beast::zero;
}
base_uint(beast::Zero)
{
*this = beast::zero;
}
explicit base_uint (Blob const& vch)
{

View File

@@ -61,6 +61,10 @@ public:
std::string getText () const override;
Json::Value getJson (int options) const override;
/** Returns the 'key' (or 'index') of this item.
The key identifies this entry's position in
the SHAMap associative container.
*/
uint256 const& getIndex () const
{
return mIndex;
@@ -93,15 +97,15 @@ public:
return mFormat;
}
bool isThreadedType (); // is this a ledger entry that can be threaded
bool isThreaded (); // is this ledger entry actually threaded
bool hasOneOwner (); // This node has one other node that owns it
bool hasTwoOwners (); // This node has two nodes that own it (like ripple balance)
RippleAddress getOwner ();
RippleAddress getFirstOwner ();
RippleAddress getSecondOwner ();
uint256 getThreadedTransaction ();
std::uint32_t getThreadedLedger ();
bool isThreadedType() const; // is this a ledger entry that can be threaded
bool isThreaded () const; // is this ledger entry actually threaded
bool hasOneOwner () const; // This node has one other node that owns it
bool hasTwoOwners () const; // This node has two nodes that own it (like ripple balance)
RippleAddress getOwner () const;
RippleAddress getFirstOwner () const;
RippleAddress getSecondOwner () const;
uint256 getThreadedTransaction () const;
std::uint32_t getThreadedLedger () const;
bool thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256 & prevTxID,
std::uint32_t & prevLedgerID);

View File

@@ -118,22 +118,47 @@ Json::Value STLedgerEntry::getJson (int options) const
return ret;
}
bool STLedgerEntry::isThreadedType ()
bool STLedgerEntry::isThreadedType () const
{
return getFieldIndex (sfPreviousTxnID) != -1;
}
bool STLedgerEntry::isThreaded ()
bool STLedgerEntry::isThreaded () const
{
return isFieldPresent (sfPreviousTxnID);
}
uint256 STLedgerEntry::getThreadedTransaction ()
bool STLedgerEntry::hasOneOwner () const
{
return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
}
bool STLedgerEntry::hasTwoOwners () const
{
return mType == ltRIPPLE_STATE;
}
RippleAddress STLedgerEntry::getOwner () const
{
return getFieldAccount (sfAccount);
}
RippleAddress STLedgerEntry::getFirstOwner () const
{
return RippleAddress::createAccountID (getFieldAmount (sfLowLimit).getIssuer ());
}
RippleAddress STLedgerEntry::getSecondOwner () const
{
return RippleAddress::createAccountID (getFieldAmount (sfHighLimit).getIssuer ());
}
uint256 STLedgerEntry::getThreadedTransaction () const
{
return getFieldH256 (sfPreviousTxnID);
}
std::uint32_t STLedgerEntry::getThreadedLedger ()
std::uint32_t STLedgerEntry::getThreadedLedger () const
{
return getFieldU32 (sfPreviousTxnLgrSeq);
}
@@ -158,29 +183,4 @@ bool STLedgerEntry::thread (uint256 const& txID, std::uint32_t ledgerSeq,
return true;
}
bool STLedgerEntry::hasOneOwner ()
{
return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
}
bool STLedgerEntry::hasTwoOwners ()
{
return mType == ltRIPPLE_STATE;
}
RippleAddress STLedgerEntry::getOwner ()
{
return getFieldAccount (sfAccount);
}
RippleAddress STLedgerEntry::getFirstOwner ()
{
return RippleAddress::createAccountID (getFieldAmount (sfLowLimit).getIssuer ());
}
RippleAddress STLedgerEntry::getSecondOwner ()
{
return RippleAddress::createAccountID (getFieldAmount (sfHighLimit).getIssuer ());
}
} // ripple

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
namespace ripple {
@@ -62,7 +63,8 @@ Json::Value doAccountInfo (RPC::Context& context)
return jvAccepted;
AccountState::pointer asAccepted =
context.netOps.getAccountState (ledger, naAccount);
getAccountState(*ledger, naAccount,
getApp().getSLECache());
if (asAccepted)
{
@@ -71,7 +73,8 @@ Json::Value doAccountInfo (RPC::Context& context)
// See if there's a SignerEntries for this account.
Account const account = naAccount.getAccountID ();
uint256 const signerListIndex = getSignerListIndex (account);
SLE::pointer signerList = ledger->getSLEi (signerListIndex);
auto const signerList = fetch(*ledger, signerListIndex,
getApp().getSLECache());
if (signerList)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/Tuning.h>
#include <ripple/app/paths/RippleState.h>
@@ -100,7 +101,8 @@ Json::Value doAccountLines (RPC::Context& context)
return result;
}
if (! ledger->hasAccount (rippleAddress))
if (! ledger->exists(getAccountRootIndex(
rippleAddress.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
std::string strPeer (params.isMember (jss::peer)
@@ -166,7 +168,8 @@ Json::Value doAccountLines (RPC::Context& context)
return RPC::expected_field_error (jss::marker, "string");
startAfter.SetHex (marker.asString ());
SLE::pointer sleLine (ledger->getSLEi (startAfter));
auto const sleLine = fetch(*ledger, startAfter,
getApp().getSLECache());
if (sleLine == nullptr || sleLine->getType () != ltRIPPLE_STATE)
return rpcError (rpcINVALID_PARAMS);
@@ -179,7 +182,7 @@ Json::Value doAccountLines (RPC::Context& context)
return rpcError (rpcINVALID_PARAMS);
// Caller provided the first line (startAfter), add it as first result
auto const line (RippleState::makeItem (raAccount, sleLine));
auto const line = RippleState::makeItem (raAccount, sleLine);
if (line == nullptr)
return rpcError (rpcINVALID_PARAMS);
@@ -193,10 +196,12 @@ Json::Value doAccountLines (RPC::Context& context)
visitData.items.reserve (++reserve);
}
if (! ledger->visitAccountItems (raAccount, startAfter, startHint, reserve,
[&visitData](SLE::ref sleCur)
if (! forEachItemAfter(*ledger, raAccount, getApp().getSLECache(),
startAfter, startHint, reserve,
[&visitData](std::shared_ptr<SLE const> const& sleCur)
{
auto const line (RippleState::makeItem (visitData.accountID, sleCur));
auto const line =
RippleState::makeItem (visitData.accountID, sleCur);
if (line != nullptr &&
(! visitData.rippleAddressPeer.isValid () ||
visitData.raPeerAccount == line->getAccountIDPeer ()))
@@ -216,7 +221,7 @@ Json::Value doAccountLines (RPC::Context& context)
result[jss::limit] = limit;
RippleState::pointer line (visitData.items.back ());
result[jss::marker] = to_string (line->peekSLE ().getIndex ());
result[jss::marker] = to_string (line->key());
visitData.items.pop_back ();
}

View File

@@ -68,7 +68,8 @@ Json::Value doAccountObjects (RPC::Context& context)
}
}
if (! ledger->hasAccount (raAccount))
if (! ledger->exists(getAccountRootIndex(
raAccount.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
auto type = ltINVALID;

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/Tuning.h>
namespace ripple {
@@ -62,7 +63,8 @@ Json::Value doAccountOffers (RPC::Context& context)
if (bIndex)
result[jss::account_index] = iIndex;
if (! ledger->hasAccount (rippleAddress))
if (! ledger->exists(getAccountRootIndex(
rippleAddress.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
unsigned int limit;
@@ -88,7 +90,7 @@ Json::Value doAccountOffers (RPC::Context& context)
Account const& raAccount (rippleAddress.getAccountID ());
Json::Value& jsonOffers (result[jss::offers] = Json::arrayValue);
std::vector <SLE::pointer> offers;
std::vector <std::shared_ptr<SLE const>> offers;
unsigned int reserve (limit);
uint256 startAfter;
std::uint64_t startHint;
@@ -103,7 +105,8 @@ Json::Value doAccountOffers (RPC::Context& context)
return RPC::expected_field_error (jss::marker, "string");
startAfter.SetHex (marker.asString ());
SLE::pointer sleOffer (ledger->getSLEi (startAfter));
auto const sleOffer = fetch (*ledger, startAfter,
getApp().getSLECache());
if (sleOffer == nullptr ||
sleOffer->getType () != ltOFFER ||
@@ -130,8 +133,9 @@ Json::Value doAccountOffers (RPC::Context& context)
offers.reserve (++reserve);
}
if (! ledger->visitAccountItems (raAccount, startAfter, startHint, reserve,
[&offers](SLE::ref offer)
if (! forEachItemAfter(*ledger, raAccount, getApp().getSLECache(),
startAfter, startHint, reserve,
[&offers](std::shared_ptr<SLE const> const& offer)
{
if (offer->getType () == ltOFFER)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
namespace ripple {
@@ -207,7 +208,8 @@ Json::Value doLedgerEntry (RPC::Context& context)
if (uNodeIndex.isNonZero ())
{
auto sleNode = lpLedger->getSLEi(uNodeIndex);
auto const sleNode = fetch(*lpLedger, uNodeIndex,
getApp().getSLECache());
if (context.params.isMember(jss::binary))
bNodeBinary = context.params[jss::binary].asBool();

View File

@@ -63,27 +63,30 @@ Json::Value doLedgerRequest (RPC::Context& context)
if (ledgerIndex >= ledger->getLedgerSeq())
return RPC::make_param_error("Ledger index too large");
auto const j =
deprecatedLogs().journal("RPCHandler");
// Try to get the hash of the desired ledger from the validated ledger
ledgerHash = ledger->getLedgerHash (ledgerIndex);
if (ledgerHash == zero)
auto ledgerHash = hashOfSeq(*ledger, ledgerIndex,
getApp().getSLECache(), j);
if (! ledgerHash)
{
// Find a ledger more likely to have the hash of the desired ledger
auto refIndex = (ledgerIndex + 255) & (~255);
auto refHash = ledger->getLedgerHash (refIndex);
assert (refHash.isNonZero ());
auto refHash = hashOfSeq(*ledger, refIndex,
getApp().getSLECache(), j);
assert(refHash);
ledger = ledgerMaster.getLedgerByHash (refHash);
if (!ledger)
ledger = ledgerMaster.getLedgerByHash (*refHash);
if (! ledger)
{
// We don't have the ledger we need to figure out which ledger
// they want. Try to get it.
if (auto il = getApp().getInboundLedgers().acquire (
refHash, refIndex, InboundLedger::fcGENERIC))
*refHash, refIndex, InboundLedger::fcGENERIC))
return getJson (LedgerFill (*il));
if (auto il = getApp().getInboundLedgers().find (refHash))
if (auto il = getApp().getInboundLedgers().find (*refHash))
{
Json::Value jvResult = il->getJson (0);
@@ -95,8 +98,11 @@ Json::Value doLedgerRequest (RPC::Context& context)
return Json::Value();
}
ledgerHash = ledger->getLedgerHash (ledgerIndex);
assert (ledgerHash.isNonZero ());
ledgerHash = hashOfSeq(*ledger, ledgerIndex,
getApp().getSLECache(), j);
assert (ledgerHash);
if (! ledgerHash)
ledgerHash = zero; // kludge
}
}

View File

@@ -106,15 +106,17 @@ Json::Value doNoRippleCheck (RPC::Context& context)
return result;
}
AccountState::pointer accountState = ledger->getAccountState (rippleAddress);
AccountState::pointer accountState =
getAccountState(*ledger, rippleAddress,
getApp().getSLECache());
if (! accountState)
return rpcError (rpcACT_NOT_FOUND);
std::uint32_t seq = accountState->peekSLE().getFieldU32 (sfSequence);
std::uint32_t seq = accountState->sle().getFieldU32 (sfSequence);
Json::Value& problems = (result["problems"] = Json::arrayValue);
bool bDefaultRipple = accountState->peekSLE().getFieldU32 (sfFlags) & lsfDefaultRipple;
bool bDefaultRipple = accountState->sle().getFieldU32 (sfFlags) & lsfDefaultRipple;
if (bDefaultRipple & ! roleGateway)
{
@@ -135,8 +137,9 @@ Json::Value doNoRippleCheck (RPC::Context& context)
auto const accountID = rippleAddress.getAccountID ();
ledger->visitAccountItems (accountID, uint256(), 0, limit,
[&](SLE::ref ownedItem)
forEachItemAfter (*ledger, accountID, getApp().getSLECache(),
uint256(), 0, limit,
[&](std::shared_ptr<SLE const> const& ownedItem)
{
if (ownedItem->getType() == ltRIPPLE_STATE)
{

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/rpc/impl/Accounts.h>
#include <ripple/app/main/Application.h>
namespace ripple {
namespace RPC {
@@ -40,7 +41,8 @@ Json::Value accounts (
naAccount.setAccountPublic (naMasterGenerator, uIndex++);
AccountState::pointer as = netOps.getAccountState (lrLedger, naAccount);
AccountState::pointer as =
getAccountState (*lrLedger, naAccount, getApp().getSLECache());
if (as)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <ripple/rpc/impl/GetAccountObjects.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/JsonFields.h>
@@ -38,8 +39,9 @@ getAccountObjects (Ledger const& ledger, Account const& account,
found = true;
}
auto dir = ledger.getDirNode (dirIndex);
if (dir == nullptr)
auto dir = fetch(ledger, dirIndex,
getApp().getSLECache(), ltDIR_NODE);
if (! dir)
return false;
std::uint32_t i = 0;
@@ -60,7 +62,8 @@ getAccountObjects (Ledger const& ledger, Account const& account,
for (; iter != entries.end (); ++iter)
{
auto const sleNode = ledger.getSLEi (*iter);
auto const sleNode = fetch(ledger, *iter,
getApp().getSLECache());
if (type == ltINVALID || sleNode->getType () == type)
{
jvObjects.append (sleNode->getJson (0));
@@ -84,9 +87,10 @@ getAccountObjects (Ledger const& ledger, Account const& account,
if (nodeIndex == 0)
return true;
dirIndex = getDirNodeIndex (rootDirIndex, nodeIndex);
dir = ledger.getDirNode (dirIndex);
if (dir == nullptr)
dirIndex = getDirNodeIndex (rootDirIndex, nodeIndex);
dir = fetch(ledger, dirIndex,
getApp().getSLECache(), ltDIR_NODE);
if (! dir)
return true;
if (i == limit)

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerFees.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/TransactionSign.h>
#include <ripple/rpc/impl/KeypairForSignature.h>
#include <ripple/app/paths/FindPaths.h>
@@ -111,7 +112,8 @@ void TxnSignApiFacade::snapshotAccountState (RippleAddress const& accountID)
ledger_ = netOPs_->getCurrentLedger ();
accountID_ = accountID;
accountState_ = netOPs_->getAccountState (ledger_, accountID_);
accountState_ = getAccountState (
*ledger_, accountID_, getApp().getSLECache());
}
bool TxnSignApiFacade::isValidAccount () const
@@ -127,7 +129,7 @@ std::uint32_t TxnSignApiFacade::getSeq () const
if (!ledger_) // Unit testing.
return 0;
return accountState_->getSeq ();
return accountState_->sle().getFieldU32(sfSequence);
}
Transaction::pointer TxnSignApiFacade::processTransaction (
@@ -192,11 +194,8 @@ bool TxnSignApiFacade::hasAccountRoot () const
{
if (!netOPs_) // Unit testing.
return true;
SLE::pointer const sleAccountRoot =
ledger_->getSLEi(getAccountRootIndex(accountID_));
return static_cast <bool> (sleAccountRoot);
return ledger_->exists(
getAccountRootIndex(accountID_));
}
error_code_i acctMatchesPubKey (
@@ -217,7 +216,7 @@ error_code_i acctMatchesPubKey (
}
// If we *can* get to the accountRoot, check for MASTER_DISABLED
STLedgerEntry const& sle = accountState->peekSLE ();
auto const& sle = accountState->sle();
if (isMasterKey)
{
if (sle.isFlag(lsfDisableMaster))
@@ -248,11 +247,13 @@ error_code_i TxnSignApiFacade::multiAcctMatchesPubKey (
RippleAddress const& publicKey) const
{
AccountState::pointer accountState;
// VFALCO Do we need to check netOPs_?
if (netOPs_ && ledger_)
// If it's available, get the AccountState for the multi-signer's
// accountID. It's okay if the AccountState is not available,
// since they might be signing with a phantom (unfunded) account.
accountState = netOPs_->getAccountState (ledger_, accountID);
accountState = getAccountState (
*ledger_, accountID, getApp().getSLECache());
return acctMatchesPubKey (accountState, accountID, publicKey);
}

View File

@@ -43,7 +43,15 @@ public:
Slice slice() const;
uint256 const&
key() const
{
return mTag;
}
// DEPRECATED
uint256 const& getTag() const;
Blob const& peekData() const;
Serializer& peekSerializer();