mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
37
src/ripple/app/ledger/SLECache.h
Normal file
37
src/ripple/app/ledger/SLECache.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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 (...)
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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())))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user