mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Refactor LedgerEntrySet:
* Remove duplicate:
This changes behavior to fix an apparent bug. The
copy will now correctly inherit mParams instead
of reverting to tapNONE
* Tidy up LedgerEntrySet declarations
* Tidy up TransactionEngine
* Tidy PathCursor declarations
* Add LedgerEntrySet::apply
* Add LedgerEntrySet ctor
* Add Keylet, keylet namespace
* Add defaulted copy members
* Use optional in TransactionEngine
* Use optional<LedgerEntrySet> in PathState
* Return shared_ptr in Ledger::fetch
* Don't call entryCache with zero
* Deprecate invalidate
* Remove default constructor
* Remove unused container API
* Remove CountedObject base class
* Remove insert, clear
* Remove entryCreate overload
* Remove unused and tidy up STLedgerEntry
* Make getEntry private and tidy
* Replace members with adjustOwnerCount free function
* Replace accountFunds with funds free function
This commit is contained in:
committed by
Nik Bougalis
parent
aead038215
commit
d21171b21e
@@ -99,7 +99,8 @@ void AcceptedLedgerTx::buildJson ()
|
|||||||
if (account != amount.issue ().account)
|
if (account != amount.issue ().account)
|
||||||
{
|
{
|
||||||
LedgerEntrySet les (mLedger, tapNONE, true);
|
LedgerEntrySet les (mLedger, tapNONE, true);
|
||||||
auto const ownerFunds (les.accountFunds (account, amount, fhIGNORE_FREEZE));
|
auto const ownerFunds (funds(
|
||||||
|
les, account, amount, fhIGNORE_FREEZE));
|
||||||
|
|
||||||
mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText ();
|
mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -984,20 +984,19 @@ Ledger::insert (SLE const& sle)
|
|||||||
assert(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<SLE>
|
std::shared_ptr<SLE>
|
||||||
Ledger::fetch (uint256 const& key,
|
Ledger::fetch (uint256 const& key,
|
||||||
boost::optional<LedgerEntryType> type) const
|
boost::optional<LedgerEntryType> type) const
|
||||||
{
|
{
|
||||||
auto const item =
|
auto const item =
|
||||||
mAccountStateMap->peekItem(key);
|
mAccountStateMap->peekItem(key);
|
||||||
if (! item)
|
if (! item)
|
||||||
return boost::none;
|
return nullptr;
|
||||||
boost::optional<SLE> result;
|
auto const sle = std::make_shared<SLE>(
|
||||||
result.emplace(item->peekSerializer(),
|
item->peekSerializer(), item->getTag());
|
||||||
item->getTag());
|
if (type && sle->getType() != type)
|
||||||
if (type && result->getType() != type)
|
return nullptr;
|
||||||
return {};
|
return sle;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1171,7 +1170,8 @@ void Ledger::updateSkipList ()
|
|||||||
bool created;
|
bool created;
|
||||||
if (! sle)
|
if (! sle)
|
||||||
{
|
{
|
||||||
sle.emplace(ltLEDGER_HASHES, key);
|
sle = std::make_shared<SLE>(
|
||||||
|
ltLEDGER_HASHES, key);
|
||||||
created = true;
|
created = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1198,7 +1198,8 @@ void Ledger::updateSkipList ()
|
|||||||
bool created;
|
bool created;
|
||||||
if (! sle)
|
if (! sle)
|
||||||
{
|
{
|
||||||
sle.emplace(ltLEDGER_HASHES, key);
|
sle = std::make_shared<SLE>(
|
||||||
|
ltLEDGER_HASHES, key);
|
||||||
created = true;
|
created = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <ripple/app/tx/TransactionMeta.h>
|
#include <ripple/app/tx/TransactionMeta.h>
|
||||||
#include <ripple/app/ledger/SLECache.h>
|
#include <ripple/app/ledger/SLECache.h>
|
||||||
#include <ripple/app/misc/AccountState.h>
|
#include <ripple/app/misc/AccountState.h>
|
||||||
|
#include <ripple/protocol/Indexes.h>
|
||||||
#include <ripple/protocol/STLedgerEntry.h>
|
#include <ripple/protocol/STLedgerEntry.h>
|
||||||
#include <ripple/basics/CountedObject.h>
|
#include <ripple/basics/CountedObject.h>
|
||||||
#include <ripple/protocol/Serializer.h>
|
#include <ripple/protocol/Serializer.h>
|
||||||
@@ -138,10 +139,16 @@ public:
|
|||||||
then boost::none is returned.
|
then boost::none is returned.
|
||||||
@return `empty` if the key is not present
|
@return `empty` if the key is not present
|
||||||
*/
|
*/
|
||||||
boost::optional<SLE>
|
std::shared_ptr<SLE>
|
||||||
fetch (uint256 const& key, boost::optional<
|
fetch (uint256 const& key, boost::optional<
|
||||||
LedgerEntryType> type = boost::none) const;
|
LedgerEntryType> type = boost::none) const;
|
||||||
|
|
||||||
|
std::shared_ptr<SLE>
|
||||||
|
fetch (Keylet const& k) const
|
||||||
|
{
|
||||||
|
return fetch(k.key, k.type);
|
||||||
|
}
|
||||||
|
|
||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
// Retrieve immutable ledger entry
|
// Retrieve immutable ledger entry
|
||||||
SLE::pointer getSLEi (uint256 const& uHash) const;
|
SLE::pointer getSLEi (uint256 const& uHash) const;
|
||||||
|
|||||||
@@ -34,31 +34,76 @@ namespace ripple {
|
|||||||
// VFALCO TODO Replace this macro with a documented language constant
|
// VFALCO TODO Replace this macro with a documented language constant
|
||||||
// NOTE Is this part of the protocol?
|
// NOTE Is this part of the protocol?
|
||||||
//
|
//
|
||||||
#define DIR_NODE_MAX 32
|
#define DIR_NODE_MAX 32
|
||||||
|
|
||||||
void LedgerEntrySet::init (Ledger::ref ledger, uint256 const& transactionID,
|
LedgerEntrySet::LedgerEntrySet (LedgerEntrySet const& other)
|
||||||
std::uint32_t ledgerID, TransactionEngineParams params)
|
: mLedger(other.mLedger)
|
||||||
|
, mEntries(other.mEntries)
|
||||||
|
, mDeferredCredits(other.mDeferredCredits)
|
||||||
|
, mSet(other.mSet)
|
||||||
|
// VFALCO NOTE This is a change in behavior,
|
||||||
|
// previous version set tapNONE
|
||||||
|
, mParams(other.mParams)
|
||||||
|
, mSeq(other.mSeq + 1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LedgerEntrySet::LedgerEntrySet(Ledger::ref ledger,
|
||||||
|
uint256 const& transactionID,
|
||||||
|
std::uint32_t ledgerID,
|
||||||
|
TransactionEngineParams params)
|
||||||
|
: mLedger(ledger)
|
||||||
|
, mParams(params)
|
||||||
{
|
{
|
||||||
mEntries.clear ();
|
|
||||||
if (mDeferredCredits)
|
|
||||||
mDeferredCredits->clear ();
|
|
||||||
mLedger = ledger;
|
|
||||||
mSet.init (transactionID, ledgerID);
|
mSet.init (transactionID, ledgerID);
|
||||||
mParams = params;
|
|
||||||
mSeq = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerEntrySet::clear ()
|
LedgerEntrySet::LedgerEntrySet (Ledger::ref ledger,
|
||||||
|
TransactionEngineParams tep, bool immutable)
|
||||||
|
: mLedger (ledger)
|
||||||
|
, mParams (tep)
|
||||||
|
, mImmutable (immutable)
|
||||||
{
|
{
|
||||||
mEntries.clear ();
|
|
||||||
mSet.clear ();
|
|
||||||
if (mDeferredCredits)
|
|
||||||
mDeferredCredits->clear ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LedgerEntrySet LedgerEntrySet::duplicate () const
|
void LedgerEntrySet::apply()
|
||||||
{
|
{
|
||||||
return LedgerEntrySet (mLedger, mEntries, mSet, mSeq + 1, mDeferredCredits);
|
// Write back the account states
|
||||||
|
for (auto const& item : mEntries)
|
||||||
|
{
|
||||||
|
// VFALCO TODO rvalue move the mEntry, make
|
||||||
|
// sure the mNodes is not used after
|
||||||
|
// this function is called.
|
||||||
|
auto sle = item.second.mEntry;
|
||||||
|
switch (item.second.mAction)
|
||||||
|
{
|
||||||
|
case taaNONE:
|
||||||
|
assert (false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case taaCACHED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case taaCREATE:
|
||||||
|
// VFALCO Is this logging necessary anymore?
|
||||||
|
WriteLog (lsDEBUG, LedgerEntrySet) <<
|
||||||
|
"applyTransaction: taaCREATE: " << sle->getText ();
|
||||||
|
mLedger->insert(*sle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case taaMODIFY:
|
||||||
|
WriteLog (lsDEBUG, LedgerEntrySet) <<
|
||||||
|
"applyTransaction: taaMODIFY: " << sle->getText ();
|
||||||
|
mLedger->replace(*sle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case taaDELETE:
|
||||||
|
WriteLog (lsDEBUG, LedgerEntrySet) <<
|
||||||
|
"applyTransaction: taaDELETE: " << sle->getText ();
|
||||||
|
mLedger->erase(item.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerEntrySet::swapWith (LedgerEntrySet& e)
|
void LedgerEntrySet::swapWith (LedgerEntrySet& e)
|
||||||
@@ -74,7 +119,7 @@ void LedgerEntrySet::swapWith (LedgerEntrySet& e)
|
|||||||
|
|
||||||
// Find an entry in the set. If it has the wrong sequence number, copy it and update the sequence number.
|
// Find an entry in the set. If it has the wrong sequence number, copy it and update the sequence number.
|
||||||
// This is basically: copy-on-read.
|
// This is basically: copy-on-read.
|
||||||
SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction& action)
|
SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, Action& action)
|
||||||
{
|
{
|
||||||
auto it = mEntries.find (index);
|
auto it = mEntries.find (index);
|
||||||
|
|
||||||
@@ -87,7 +132,7 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction&
|
|||||||
if (it->second.mSeq != mSeq)
|
if (it->second.mSeq != mSeq)
|
||||||
{
|
{
|
||||||
assert (it->second.mSeq < mSeq);
|
assert (it->second.mSeq < mSeq);
|
||||||
it->second.mEntry = std::make_shared<STLedgerEntry> (*it->second.mEntry);
|
it->second.mEntry = std::make_shared<SLE> (*it->second.mEntry);
|
||||||
it->second.mSeq = mSeq;
|
it->second.mSeq = mSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,26 +140,15 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction&
|
|||||||
return it->second.mEntry;
|
return it->second.mEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLE::pointer LedgerEntrySet::entryCreate (LedgerEntryType letType, uint256 const& index)
|
|
||||||
{
|
|
||||||
assert (index.isNonZero ());
|
|
||||||
SLE::pointer sleNew = std::make_shared<SLE> (letType, index);
|
|
||||||
entryCreate (sleNew);
|
|
||||||
return sleNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& key)
|
SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& key)
|
||||||
{
|
{
|
||||||
|
assert(key.isNonZero ());
|
||||||
assert (mLedger);
|
assert (mLedger);
|
||||||
SLE::pointer sle;
|
SLE::pointer sle;
|
||||||
|
|
||||||
// VFALCO Shouldn't be calling this with invalid keys,
|
|
||||||
// but apparently its happening. Need to track it down.
|
|
||||||
//assert(key.isNonZero ());
|
|
||||||
|
|
||||||
if (key.isNonZero ())
|
if (key.isNonZero ())
|
||||||
{
|
{
|
||||||
LedgerEntryAction action;
|
Action action;
|
||||||
sle = getEntry (key, action);
|
sle = getEntry (key, action);
|
||||||
|
|
||||||
if (! sle)
|
if (! sle)
|
||||||
@@ -128,10 +162,7 @@ SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const&
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto maybe_sle = mLedger->fetch(key, letType);
|
sle = mLedger->fetch(key, letType);
|
||||||
if (maybe_sle)
|
|
||||||
sle = std::make_shared<SLE>(
|
|
||||||
std::move(*maybe_sle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sle)
|
if (sle)
|
||||||
@@ -160,7 +191,7 @@ void LedgerEntrySet::entryCache (SLE::ref sle)
|
|||||||
|
|
||||||
if (it == mEntries.end ())
|
if (it == mEntries.end ())
|
||||||
{
|
{
|
||||||
mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaCACHED, mSeq)));
|
mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaCACHED, mSeq)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +216,7 @@ void LedgerEntrySet::entryCreate (SLE::ref sle)
|
|||||||
|
|
||||||
if (it == mEntries.end ())
|
if (it == mEntries.end ())
|
||||||
{
|
{
|
||||||
mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaCREATE, mSeq)));
|
mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaCREATE, mSeq)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +254,7 @@ void LedgerEntrySet::entryModify (SLE::ref sle)
|
|||||||
|
|
||||||
if (it == mEntries.end ())
|
if (it == mEntries.end ())
|
||||||
{
|
{
|
||||||
mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaMODIFY, mSeq)));
|
mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaMODIFY, mSeq)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +291,7 @@ void LedgerEntrySet::entryDelete (SLE::ref sle)
|
|||||||
if (it == mEntries.end ())
|
if (it == mEntries.end ())
|
||||||
{
|
{
|
||||||
assert (false); // deleting an entry not cached?
|
assert (false); // deleting an entry not cached?
|
||||||
mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaDELETE, mSeq)));
|
mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaDELETE, mSeq)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +410,8 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
|
|||||||
|
|
||||||
if (it->second.mSeq != mSeq)
|
if (it->second.mSeq != mSeq)
|
||||||
{
|
{
|
||||||
it->second.mEntry = std::make_shared<STLedgerEntry> (*it->second.mEntry);
|
it->second.mEntry =
|
||||||
|
std::make_shared<SLE> (*it->second.mEntry);
|
||||||
it->second.mSeq = mSeq;
|
it->second.mSeq = mSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,15 +427,10 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto sle = ledger->fetch(node);
|
auto sle = ledger->fetch(node);
|
||||||
if (sle)
|
if (! sle)
|
||||||
{
|
return nullptr;
|
||||||
auto p = std::make_shared<SLE>(
|
newMods.insert (std::make_pair (node, sle));
|
||||||
std::move(*sle));
|
return sle;
|
||||||
newMods.insert (std::make_pair (node, p));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerEntrySet::threadTx (RippleAddress const& threadTo, Ledger::ref ledger,
|
bool LedgerEntrySet::threadTx (RippleAddress const& threadTo, Ledger::ref ledger,
|
||||||
@@ -611,36 +638,6 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index
|
|||||||
WriteLog (lsTRACE, LedgerEntrySet) << "Metadata:" << mSet.getJson (0);
|
WriteLog (lsTRACE, LedgerEntrySet) << "Metadata:" << mSet.getJson (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER LedgerEntrySet::dirCount (uint256 const& uRootIndex, std::uint32_t& uCount)
|
|
||||||
{
|
|
||||||
std::uint64_t uNodeDir = 0;
|
|
||||||
|
|
||||||
uCount = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SLE::pointer sleNode = entryCache (ltDIR_NODE, getDirNodeIndex (uRootIndex, uNodeDir));
|
|
||||||
|
|
||||||
if (sleNode)
|
|
||||||
{
|
|
||||||
uCount += sleNode->getFieldV256 (sfIndexes).size ();
|
|
||||||
|
|
||||||
uNodeDir = sleNode->getFieldU64 (sfIndexNext); // Get next node.
|
|
||||||
}
|
|
||||||
else if (uNodeDir)
|
|
||||||
{
|
|
||||||
WriteLog (lsWARNING, LedgerEntrySet) << "dirCount: no such node";
|
|
||||||
|
|
||||||
assert (false);
|
|
||||||
|
|
||||||
return tefBAD_LEDGER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (uNodeDir);
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LedgerEntrySet::dirIsEmpty (uint256 const& uRootIndex)
|
bool LedgerEntrySet::dirIsEmpty (uint256 const& uRootIndex)
|
||||||
{
|
{
|
||||||
std::uint64_t uNodeDir = 0;
|
std::uint64_t uNodeDir = 0;
|
||||||
@@ -679,10 +676,10 @@ TER LedgerEntrySet::dirAdd (
|
|||||||
if (!sleRoot)
|
if (!sleRoot)
|
||||||
{
|
{
|
||||||
// No root, make it.
|
// No root, make it.
|
||||||
sleRoot = entryCreate (ltDIR_NODE, uRootIndex);
|
sleRoot = std::make_shared<SLE>(ltDIR_NODE, uRootIndex);
|
||||||
sleRoot->setFieldH256 (sfRootIndex, uRootIndex);
|
sleRoot->setFieldH256 (sfRootIndex, uRootIndex);
|
||||||
|
entryCreate (sleRoot);
|
||||||
fDescriber (sleRoot, true);
|
fDescriber (sleRoot, true);
|
||||||
|
|
||||||
sleNode = sleRoot;
|
sleNode = sleRoot;
|
||||||
uNodeDir = 0;
|
uNodeDir = 0;
|
||||||
}
|
}
|
||||||
@@ -726,8 +723,10 @@ TER LedgerEntrySet::dirAdd (
|
|||||||
entryModify (sleRoot);
|
entryModify (sleRoot);
|
||||||
|
|
||||||
// Create the new node.
|
// Create the new node.
|
||||||
sleNode = entryCreate (ltDIR_NODE, getDirNodeIndex (uRootIndex, uNodeDir));
|
sleNode = std::make_shared<SLE>(
|
||||||
|
ltDIR_NODE, getDirNodeIndex(uRootIndex, uNodeDir));
|
||||||
sleNode->setFieldH256 (sfRootIndex, uRootIndex);
|
sleNode->setFieldH256 (sfRootIndex, uRootIndex);
|
||||||
|
entryCreate (sleNode);
|
||||||
|
|
||||||
if (uNodeDir != 1)
|
if (uNodeDir != 1)
|
||||||
sleNode->setFieldU64 (sfIndexPrevious, uNodeDir - 1);
|
sleNode->setFieldU64 (sfIndexPrevious, uNodeDir - 1);
|
||||||
@@ -1080,7 +1079,7 @@ uint256 LedgerEntrySet::getNextLedgerIndex (uint256 const& uHash)
|
|||||||
{
|
{
|
||||||
// find next node in ledger that isn't deleted by LES
|
// find next node in ledger that isn't deleted by LES
|
||||||
uint256 ledgerNext = uHash;
|
uint256 ledgerNext = uHash;
|
||||||
std::map<uint256, LedgerEntrySetEntry>::const_iterator it;
|
std::map<uint256, Item>::const_iterator it;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -1113,69 +1112,6 @@ uint256 LedgerEntrySet::getNextLedgerIndex (
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerEntrySet::incrementOwnerCount (SLE::ref sleAccount)
|
|
||||||
{
|
|
||||||
increaseOwnerCount (sleAccount, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerEntrySet::incrementOwnerCount (Account const& owner)
|
|
||||||
{
|
|
||||||
increaseOwnerCount(
|
|
||||||
entryCache (ltACCOUNT_ROOT, getAccountRootIndex (owner)), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LedgerEntrySet::increaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch)
|
|
||||||
{
|
|
||||||
assert (sleAccount);
|
|
||||||
|
|
||||||
std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount);
|
|
||||||
std::uint32_t new_count = current_count + howMuch;
|
|
||||||
|
|
||||||
// Check for integer overflow -- well defined behavior on unsigned.
|
|
||||||
if (new_count < current_count)
|
|
||||||
{
|
|
||||||
WriteLog (lsFATAL, LedgerEntrySet) <<
|
|
||||||
"Account " << sleAccount->getFieldAccount160 (sfAccount) <<
|
|
||||||
" owner count exceeds max!";
|
|
||||||
new_count = std::numeric_limits<std::uint32_t>::max ();
|
|
||||||
}
|
|
||||||
sleAccount->setFieldU32 (sfOwnerCount, new_count);
|
|
||||||
entryModify (sleAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerEntrySet::decrementOwnerCount (SLE::ref sleAccount)
|
|
||||||
{
|
|
||||||
decreaseOwnerCount (sleAccount, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LedgerEntrySet::decrementOwnerCount (Account const& owner)
|
|
||||||
{
|
|
||||||
decreaseOwnerCount(
|
|
||||||
entryCache (ltACCOUNT_ROOT, getAccountRootIndex (owner)), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LedgerEntrySet::decreaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch)
|
|
||||||
{
|
|
||||||
assert (sleAccount);
|
|
||||||
|
|
||||||
std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount);
|
|
||||||
std::uint32_t new_count = current_count - howMuch;
|
|
||||||
|
|
||||||
// Check for integer underflow -- well defined behavior on unsigned.
|
|
||||||
if (new_count > current_count)
|
|
||||||
{
|
|
||||||
WriteLog (lsFATAL, LedgerEntrySet) <<
|
|
||||||
"Account " << sleAccount->getFieldAccount160 (sfAccount) <<
|
|
||||||
" owner count set below 0!";
|
|
||||||
new_count = 0;
|
|
||||||
assert (false); // "This is a dangerous place." Stop in a debug build.
|
|
||||||
}
|
|
||||||
sleAccount->setFieldU32 (sfOwnerCount, new_count);
|
|
||||||
entryModify (sleAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
||||||
{
|
{
|
||||||
if (!sleOffer)
|
if (!sleOffer)
|
||||||
@@ -1197,7 +1133,8 @@ TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
|||||||
false, uBookNode, uDirectory, offerIndex, true, false);
|
false, uBookNode, uDirectory, offerIndex, true, false);
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
decrementOwnerCount (owner);
|
adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT,
|
||||||
|
getAccountRootIndex(owner)), -1);
|
||||||
|
|
||||||
entryDelete (sleOffer);
|
entryDelete (sleOffer);
|
||||||
|
|
||||||
@@ -1333,43 +1270,6 @@ bool LedgerEntrySet::isFrozen(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the funds available for account for a currency/issuer.
|
|
||||||
// Use when you need a default for rippling account's currency.
|
|
||||||
// XXX Should take into account quality?
|
|
||||||
// --> saDefault/currency/issuer
|
|
||||||
// <-- saFunds: Funds available. May be negative.
|
|
||||||
//
|
|
||||||
// If the issuer is the same as account, funds are unlimited, use result is
|
|
||||||
// saDefault.
|
|
||||||
STAmount LedgerEntrySet::accountFunds (
|
|
||||||
Account const& account, STAmount const& saDefault, FreezeHandling zeroIfFrozen)
|
|
||||||
{
|
|
||||||
STAmount saFunds;
|
|
||||||
|
|
||||||
if (!saDefault.native () && saDefault.getIssuer () == account)
|
|
||||||
{
|
|
||||||
saFunds = saDefault;
|
|
||||||
|
|
||||||
WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" <<
|
|
||||||
" account=" << to_string (account) <<
|
|
||||||
" saDefault=" << saDefault.getFullText () <<
|
|
||||||
" SELF-FUNDED";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
saFunds = accountHolds (
|
|
||||||
account, saDefault.getCurrency (), saDefault.getIssuer (),
|
|
||||||
zeroIfFrozen);
|
|
||||||
|
|
||||||
WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" <<
|
|
||||||
" account=" << to_string (account) <<
|
|
||||||
" saDefault=" << saDefault.getFullText () <<
|
|
||||||
" saFunds=" << saFunds.getFullText ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return saFunds;
|
|
||||||
}
|
|
||||||
|
|
||||||
TER LedgerEntrySet::trustCreate (
|
TER LedgerEntrySet::trustCreate (
|
||||||
const bool bSrcHigh,
|
const bool bSrcHigh,
|
||||||
Account const& uSrcAccountID,
|
Account const& uSrcAccountID,
|
||||||
@@ -1393,7 +1293,9 @@ TER LedgerEntrySet::trustCreate (
|
|||||||
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||||
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||||
|
|
||||||
SLE::pointer sleRippleState = entryCreate (ltRIPPLE_STATE, uIndex);
|
auto sleRippleState = std::make_shared<SLE>(
|
||||||
|
ltRIPPLE_STATE, uIndex);
|
||||||
|
entryCreate (sleRippleState);
|
||||||
|
|
||||||
std::uint64_t uLowNode;
|
std::uint64_t uLowNode;
|
||||||
std::uint64_t uHighNode;
|
std::uint64_t uHighNode;
|
||||||
@@ -1469,7 +1371,7 @@ TER LedgerEntrySet::trustCreate (
|
|||||||
}
|
}
|
||||||
|
|
||||||
sleRippleState->setFieldU32 (sfFlags, uFlags);
|
sleRippleState->setFieldU32 (sfFlags, uFlags);
|
||||||
incrementOwnerCount (sleAccount);
|
adjustOwnerCount(*this, sleAccount, 1);
|
||||||
|
|
||||||
// ONLY: Create ripple balance.
|
// ONLY: Create ripple balance.
|
||||||
sleRippleState->setFieldAmount (sfBalance, bSetHigh ? -saBalance : saBalance);
|
sleRippleState->setFieldAmount (sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||||
@@ -1659,7 +1561,8 @@ TER LedgerEntrySet::rippleCredit (
|
|||||||
// Sender quality out is 0.
|
// Sender quality out is 0.
|
||||||
{
|
{
|
||||||
// Clear the reserve of the sender, possibly delete the line!
|
// Clear the reserve of the sender, possibly delete the line!
|
||||||
decrementOwnerCount (uSenderID);
|
adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT,
|
||||||
|
getAccountRootIndex(uSenderID)), -1);
|
||||||
|
|
||||||
// Clear reserve flag.
|
// Clear reserve flag.
|
||||||
sleRippleState->setFieldU32 (
|
sleRippleState->setFieldU32 (
|
||||||
@@ -1881,9 +1784,9 @@ bool LedgerEntrySet::checkState (
|
|||||||
{
|
{
|
||||||
std::uint32_t const flags (state->getFieldU32 (sfFlags));
|
std::uint32_t const flags (state->getFieldU32 (sfFlags));
|
||||||
|
|
||||||
auto sender_account = entryCache (ltACCOUNT_ROOT,
|
auto sle = entryCache (ltACCOUNT_ROOT,
|
||||||
getAccountRootIndex (sender));
|
getAccountRootIndex (sender));
|
||||||
assert (sender_account);
|
assert (sle);
|
||||||
|
|
||||||
// YYY Could skip this if rippling in reverse.
|
// YYY Could skip this if rippling in reverse.
|
||||||
if (before > zero
|
if (before > zero
|
||||||
@@ -1893,7 +1796,7 @@ bool LedgerEntrySet::checkState (
|
|||||||
&& (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
|
&& (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
|
||||||
// Sender reserve is set.
|
// Sender reserve is set.
|
||||||
&& static_cast <bool> (flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
|
&& static_cast <bool> (flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
|
||||||
static_cast <bool> (sender_account->getFlags() & lsfDefaultRipple)
|
static_cast <bool> (sle->getFlags() & lsfDefaultRipple)
|
||||||
&& !(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze))
|
&& !(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze))
|
||||||
&& !state->getFieldAmount (
|
&& !state->getFieldAmount (
|
||||||
!bSenderHigh ? sfLowLimit : sfHighLimit)
|
!bSenderHigh ? sfLowLimit : sfHighLimit)
|
||||||
@@ -1905,8 +1808,9 @@ bool LedgerEntrySet::checkState (
|
|||||||
!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
|
!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
|
||||||
// Sender quality out is 0.
|
// Sender quality out is 0.
|
||||||
{
|
{
|
||||||
|
// VFALCO Where is the line being deleted?
|
||||||
// Clear the reserve of the sender, possibly delete the line!
|
// Clear the reserve of the sender, possibly delete the line!
|
||||||
decrementOwnerCount (sender_account);
|
adjustOwnerCount(*this, sle, -1);
|
||||||
|
|
||||||
// Clear reserve flag.
|
// Clear reserve flag.
|
||||||
state->setFieldU32 (sfFlags,
|
state->setFieldU32 (sfFlags,
|
||||||
@@ -2146,4 +2050,70 @@ ScopedDeferCredits::~ScopedDeferCredits ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
adjustOwnerCount (LedgerEntrySet& view,
|
||||||
|
std::shared_ptr<SLE> const& sle, int amount)
|
||||||
|
{
|
||||||
|
assert(amount != 0);
|
||||||
|
auto const current =
|
||||||
|
sle->getFieldU32 (sfOwnerCount);
|
||||||
|
auto adjusted = current + amount;
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
// Overflow is well defined on unsigned
|
||||||
|
if (adjusted < current)
|
||||||
|
{
|
||||||
|
WriteLog (lsFATAL, LedgerEntrySet) <<
|
||||||
|
"Account " << sle->getFieldAccount160(sfAccount) <<
|
||||||
|
" owner count exceeds max!";
|
||||||
|
adjusted =
|
||||||
|
std::numeric_limits<std::uint32_t>::max ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Underflow is well defined on unsigned
|
||||||
|
if (adjusted > current)
|
||||||
|
{
|
||||||
|
WriteLog (lsFATAL, LedgerEntrySet) <<
|
||||||
|
"Account " << sle->getFieldAccount160 (sfAccount) <<
|
||||||
|
" owner count set below 0!";
|
||||||
|
adjusted = 0;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sle->setFieldU32 (sfOwnerCount, adjusted);
|
||||||
|
view.entryModify (sle);
|
||||||
|
}
|
||||||
|
|
||||||
|
STAmount
|
||||||
|
funds (LedgerEntrySet& view, Account const& id,
|
||||||
|
STAmount const& saDefault, FreezeHandling freezeHandling)
|
||||||
|
{
|
||||||
|
STAmount saFunds;
|
||||||
|
|
||||||
|
if (!saDefault.native () &&
|
||||||
|
saDefault.getIssuer () == id)
|
||||||
|
{
|
||||||
|
saFunds = saDefault;
|
||||||
|
WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" <<
|
||||||
|
" account=" << to_string (id) <<
|
||||||
|
" saDefault=" << saDefault.getFullText () <<
|
||||||
|
" SELF-FUNDED";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saFunds = view.accountHolds(id,
|
||||||
|
saDefault.getCurrency(), saDefault.getIssuer(),
|
||||||
|
freezeHandling);
|
||||||
|
WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" <<
|
||||||
|
" account=" << to_string (id) <<
|
||||||
|
" saDefault=" << saDefault.getFullText () <<
|
||||||
|
" saFunds=" << saFunds.getFullText ();
|
||||||
|
}
|
||||||
|
return saFunds;
|
||||||
|
}
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
#include <ripple/app/ledger/DeferredCredits.h>
|
#include <ripple/app/ledger/DeferredCredits.h>
|
||||||
#include <ripple/basics/CountedObject.h>
|
#include <ripple/basics/CountedObject.h>
|
||||||
#include <ripple/protocol/STLedgerEntry.h>
|
#include <ripple/protocol/STLedgerEntry.h>
|
||||||
|
#include <beast/utility/noexcept.h>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -50,39 +52,12 @@ enum TransactionEngineParams
|
|||||||
tapADMIN = 0x400,
|
tapADMIN = 0x400,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LedgerEntryAction
|
|
||||||
{
|
|
||||||
taaNONE,
|
|
||||||
taaCACHED, // Unmodified.
|
|
||||||
taaMODIFY, // Modifed, must have previously been taaCACHED.
|
|
||||||
taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY.
|
|
||||||
taaCREATE, // Newly created.
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FreezeHandling
|
enum FreezeHandling
|
||||||
{
|
{
|
||||||
fhIGNORE_FREEZE,
|
fhIGNORE_FREEZE,
|
||||||
fhZERO_IF_FROZEN
|
fhZERO_IF_FROZEN
|
||||||
};
|
};
|
||||||
|
|
||||||
class LedgerEntrySetEntry
|
|
||||||
: public CountedObject <LedgerEntrySetEntry>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static char const* getCountedObjectName () { return "LedgerEntrySetEntry"; }
|
|
||||||
|
|
||||||
SLE::pointer mEntry;
|
|
||||||
LedgerEntryAction mAction;
|
|
||||||
int mSeq;
|
|
||||||
|
|
||||||
LedgerEntrySetEntry (SLE::ref e, LedgerEntryAction a, int s)
|
|
||||||
: mEntry (e)
|
|
||||||
, mAction (a)
|
|
||||||
, mSeq (s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An LES is a LedgerEntrySet.
|
/** An LES is a LedgerEntrySet.
|
||||||
|
|
||||||
It's a view into a ledger used while a transaction is processing.
|
It's a view into a ledger used while a transaction is processing.
|
||||||
@@ -91,30 +66,73 @@ public:
|
|||||||
transaction finishes, the LES is committed into the ledger to make
|
transaction finishes, the LES is committed into the ledger to make
|
||||||
the modifications. The transaction metadata is built from the LES too.
|
the modifications. The transaction metadata is built from the LES too.
|
||||||
*/
|
*/
|
||||||
/** @{ */
|
|
||||||
class LedgerEntrySet
|
class LedgerEntrySet
|
||||||
: public CountedObject <LedgerEntrySet>
|
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
using NodeToLedgerEntry =
|
||||||
|
hash_map<uint256, SLE::pointer>;
|
||||||
|
|
||||||
|
enum Action
|
||||||
|
{
|
||||||
|
taaNONE,
|
||||||
|
taaCACHED, // Unmodified.
|
||||||
|
taaMODIFY, // Modifed, must have previously been taaCACHED.
|
||||||
|
taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY.
|
||||||
|
taaCREATE, // Newly created.
|
||||||
|
};
|
||||||
|
|
||||||
|
class Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int mSeq;
|
||||||
|
Action mAction;
|
||||||
|
std::shared_ptr<SLE> mEntry;
|
||||||
|
|
||||||
|
Item (SLE::ref e, Action a, int s)
|
||||||
|
: mSeq (s)
|
||||||
|
, mAction (a)
|
||||||
|
, mEntry (e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ledger::pointer mLedger;
|
||||||
|
// Implementation requires an ordered container
|
||||||
|
std::map<uint256, Item> mEntries;
|
||||||
|
boost::optional<DeferredCredits> mDeferredCredits;
|
||||||
|
TransactionMetaSet mSet;
|
||||||
|
TransactionEngineParams mParams = tapNONE;
|
||||||
|
int mSeq = 0;
|
||||||
|
bool mImmutable = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char const* getCountedObjectName () { return "LedgerEntrySet"; }
|
LedgerEntrySet& operator= (LedgerEntrySet const&) = delete;
|
||||||
|
|
||||||
LedgerEntrySet (
|
/** Construct a copy.
|
||||||
Ledger::ref ledger, TransactionEngineParams tep, bool immutable = false)
|
Effects:
|
||||||
: mLedger (ledger), mParams (tep), mSeq (0), mImmutable (immutable)
|
The copy is identical except that
|
||||||
{
|
the sequence number is one higher.
|
||||||
}
|
*/
|
||||||
|
LedgerEntrySet (LedgerEntrySet const&);
|
||||||
|
|
||||||
LedgerEntrySet () : mParams (tapNONE), mSeq (0), mImmutable (false)
|
LedgerEntrySet (Ledger::ref ledger,
|
||||||
{
|
uint256 const& transactionID,
|
||||||
}
|
std::uint32_t ledgerID,
|
||||||
|
TransactionEngineParams params);
|
||||||
|
|
||||||
// Make a duplicate of this set.
|
LedgerEntrySet (Ledger::ref ledger,
|
||||||
LedgerEntrySet duplicate () const;
|
TransactionEngineParams tep,
|
||||||
|
bool immutable = false);
|
||||||
|
|
||||||
|
/** Apply changes to the backing ledger. */
|
||||||
|
void
|
||||||
|
apply();
|
||||||
|
|
||||||
// Swap the contents of two sets
|
// Swap the contents of two sets
|
||||||
void swapWith (LedgerEntrySet&);
|
void swapWith (LedgerEntrySet&);
|
||||||
|
|
||||||
void invalidate ()
|
// VFALCO Only called from RippleCalc.cpp
|
||||||
|
void deprecatedInvalidate()
|
||||||
{
|
{
|
||||||
mLedger.reset ();
|
mLedger.reset ();
|
||||||
mDeferredCredits.reset ();
|
mDeferredCredits.reset ();
|
||||||
@@ -135,26 +153,17 @@ public:
|
|||||||
++mSeq;
|
++mSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init (Ledger::ref ledger, uint256 const& transactionID,
|
|
||||||
std::uint32_t ledgerID, TransactionEngineParams params);
|
|
||||||
|
|
||||||
void clear ();
|
|
||||||
|
|
||||||
Ledger::pointer& getLedger ()
|
Ledger::pointer& getLedger ()
|
||||||
{
|
{
|
||||||
return mLedger;
|
return mLedger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic entry functions
|
|
||||||
SLE::pointer getEntry (uint256 const& index, LedgerEntryAction&);
|
|
||||||
|
|
||||||
void entryCache (SLE::ref); // Add this entry to the cache
|
void entryCache (SLE::ref); // Add this entry to the cache
|
||||||
void entryCreate (SLE::ref); // This entry will be created
|
void entryCreate (SLE::ref); // This entry will be created
|
||||||
void entryDelete (SLE::ref); // This entry will be deleted
|
void entryDelete (SLE::ref); // This entry will be deleted
|
||||||
void entryModify (SLE::ref); // This entry will be modified
|
void entryModify (SLE::ref); // This entry will be modified
|
||||||
|
|
||||||
// higher-level ledger functions
|
// higher-level ledger functions
|
||||||
SLE::pointer entryCreate (LedgerEntryType letType, uint256 const& uIndex);
|
|
||||||
SLE::pointer entryCache (LedgerEntryType letType, uint256 const& key);
|
SLE::pointer entryCache (LedgerEntryType letType, uint256 const& key);
|
||||||
|
|
||||||
std::shared_ptr<SLE const>
|
std::shared_ptr<SLE const>
|
||||||
@@ -177,35 +186,24 @@ public:
|
|||||||
|
|
||||||
bool dirFirst (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
bool dirFirst (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
||||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||||
|
|
||||||
bool dirFirst (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
bool dirFirst (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
||||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||||
|
|
||||||
bool dirNext (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
bool dirNext (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
||||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||||
|
|
||||||
bool dirNext (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
bool dirNext (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
||||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||||
|
|
||||||
bool dirIsEmpty (uint256 const& uDirIndex);
|
bool dirIsEmpty (uint256 const& uDirIndex);
|
||||||
|
|
||||||
TER dirCount (uint256 const& uDirIndex, std::uint32_t & uCount);
|
|
||||||
|
|
||||||
uint256 getNextLedgerIndex (uint256 const& uHash);
|
uint256 getNextLedgerIndex (uint256 const& uHash);
|
||||||
uint256 getNextLedgerIndex (uint256 const& uHash, uint256 const& uEnd);
|
uint256 getNextLedgerIndex (uint256 const& uHash, uint256 const& uEnd);
|
||||||
|
|
||||||
/** @{ */
|
|
||||||
void incrementOwnerCount (SLE::ref sleAccount);
|
|
||||||
void incrementOwnerCount (Account const& owner);
|
|
||||||
void increaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** @{ */
|
|
||||||
void decrementOwnerCount (SLE::ref sleAccount);
|
|
||||||
void decrementOwnerCount (Account const& owner);
|
|
||||||
void decreaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
// Offer functions.
|
// Offer functions.
|
||||||
TER offerDelete (SLE::pointer);
|
TER offerDelete (SLE::pointer);
|
||||||
|
|
||||||
TER offerDelete (uint256 const& offerIndex)
|
TER offerDelete (uint256 const& offerIndex)
|
||||||
{
|
{
|
||||||
return offerDelete( entryCache (ltOFFER, offerIndex));
|
return offerDelete( entryCache (ltOFFER, offerIndex));
|
||||||
@@ -220,6 +218,7 @@ public:
|
|||||||
bool isGlobalFrozen (Account const& issuer);
|
bool isGlobalFrozen (Account const& issuer);
|
||||||
|
|
||||||
void enableDeferredCredits (bool enable=true);
|
void enableDeferredCredits (bool enable=true);
|
||||||
|
|
||||||
bool areCreditsDeferred () const;
|
bool areCreditsDeferred () const;
|
||||||
|
|
||||||
TER rippleCredit (
|
TER rippleCredit (
|
||||||
@@ -229,8 +228,7 @@ public:
|
|||||||
STAmount accountHolds (
|
STAmount accountHolds (
|
||||||
Account const& account, Currency const& currency,
|
Account const& account, Currency const& currency,
|
||||||
Account const& issuer, FreezeHandling freezeHandling);
|
Account const& issuer, FreezeHandling freezeHandling);
|
||||||
STAmount accountFunds (
|
|
||||||
Account const& account, const STAmount & saDefault, FreezeHandling freezeHandling);
|
|
||||||
TER accountSend (
|
TER accountSend (
|
||||||
Account const& uSenderID, Account const& uReceiverID,
|
Account const& uSenderID, Account const& uReceiverID,
|
||||||
const STAmount & saAmount);
|
const STAmount & saAmount);
|
||||||
@@ -248,46 +246,15 @@ public:
|
|||||||
STAmount const& saSrcLimit,
|
STAmount const& saSrcLimit,
|
||||||
const std::uint32_t uSrcQualityIn = 0,
|
const std::uint32_t uSrcQualityIn = 0,
|
||||||
const std::uint32_t uSrcQualityOut = 0);
|
const std::uint32_t uSrcQualityOut = 0);
|
||||||
|
|
||||||
TER trustDelete (
|
TER trustDelete (
|
||||||
SLE::ref sleRippleState, Account const& uLowAccountID,
|
SLE::ref sleRippleState, Account const& uLowAccountID,
|
||||||
Account const& uHighAccountID);
|
Account const& uHighAccountID);
|
||||||
|
|
||||||
Json::Value getJson (int) const;
|
Json::Value getJson (int) const;
|
||||||
|
|
||||||
void calcRawMeta (Serializer&, TER result, std::uint32_t index);
|
void calcRawMeta (Serializer&, TER result, std::uint32_t index);
|
||||||
|
|
||||||
// iterator functions
|
|
||||||
using iterator = std::map<uint256, LedgerEntrySetEntry>::iterator;
|
|
||||||
using const_iterator = std::map<uint256, LedgerEntrySetEntry>::const_iterator;
|
|
||||||
|
|
||||||
bool empty () const
|
|
||||||
{
|
|
||||||
return mEntries.empty ();
|
|
||||||
}
|
|
||||||
const_iterator cbegin () const
|
|
||||||
{
|
|
||||||
return mEntries.cbegin ();
|
|
||||||
}
|
|
||||||
const_iterator cend () const
|
|
||||||
{
|
|
||||||
return mEntries.cend ();
|
|
||||||
}
|
|
||||||
const_iterator begin () const
|
|
||||||
{
|
|
||||||
return mEntries.cbegin ();
|
|
||||||
}
|
|
||||||
const_iterator end () const
|
|
||||||
{
|
|
||||||
return mEntries.cend ();
|
|
||||||
}
|
|
||||||
iterator begin ()
|
|
||||||
{
|
|
||||||
return mEntries.begin ();
|
|
||||||
}
|
|
||||||
iterator end ()
|
|
||||||
{
|
|
||||||
return mEntries.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeliveredAmount (STAmount const& amt)
|
void setDeliveredAmount (STAmount const& amt)
|
||||||
{
|
{
|
||||||
mSet.setDeliveredAmount (amt);
|
mSet.setDeliveredAmount (amt);
|
||||||
@@ -302,24 +269,7 @@ public:
|
|||||||
TER transfer_xrp (Account const& from, Account const& to, STAmount const& amount);
|
TER transfer_xrp (Account const& from, Account const& to, STAmount const& amount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ledger::pointer mLedger;
|
SLE::pointer getEntry (uint256 const& index, Action&);
|
||||||
std::map<uint256, LedgerEntrySetEntry> mEntries; // cannot be unordered!
|
|
||||||
// Defers credits made to accounts until later
|
|
||||||
boost::optional<DeferredCredits> mDeferredCredits;
|
|
||||||
|
|
||||||
using NodeToLedgerEntry = hash_map<uint256, SLE::pointer>;
|
|
||||||
|
|
||||||
TransactionMetaSet mSet;
|
|
||||||
TransactionEngineParams mParams;
|
|
||||||
int mSeq;
|
|
||||||
bool mImmutable;
|
|
||||||
|
|
||||||
LedgerEntrySet (
|
|
||||||
Ledger::ref ledger, const std::map<uint256, LedgerEntrySetEntry>& e,
|
|
||||||
const TransactionMetaSet & s, int m, boost::optional<DeferredCredits> const& ft) :
|
|
||||||
mLedger (ledger), mEntries (e), mDeferredCredits (ft), mSet (s), mParams (tapNONE),
|
|
||||||
mSeq (m), mImmutable (false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
SLE::pointer getForMod (
|
SLE::pointer getForMod (
|
||||||
uint256 const& node, Ledger::ref ledger,
|
uint256 const& node, Ledger::ref ledger,
|
||||||
@@ -359,8 +309,17 @@ private:
|
|||||||
STAmount const& amount);
|
STAmount const& amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
reconstruct (LedgerEntrySet& v, Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
v.~LedgerEntrySet();
|
||||||
|
new(&v) LedgerEntrySet(
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
using LedgerView = LedgerEntrySet;
|
using LedgerView = LedgerEntrySet;
|
||||||
/** @} */
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -382,6 +341,30 @@ std::uint32_t
|
|||||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID,
|
rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID,
|
||||||
Account const& uReceiverID, Account const& issuer);
|
Account const& uReceiverID, Account const& issuer);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// API
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Adjust the owner count up or down. */
|
||||||
|
void
|
||||||
|
adjustOwnerCount (LedgerEntrySet& view,
|
||||||
|
std::shared_ptr<SLE> const& sle, int amount);
|
||||||
|
|
||||||
|
// Returns the funds available for account for a currency/issuer.
|
||||||
|
// Use when you need a default for rippling account's currency.
|
||||||
|
// XXX Should take into account quality?
|
||||||
|
// --> saDefault/currency/issuer
|
||||||
|
// <-- saFunds: Funds available. May be negative.
|
||||||
|
//
|
||||||
|
// If the issuer is the same as account, funds are unlimited, use result is
|
||||||
|
// saDefault.
|
||||||
|
STAmount
|
||||||
|
funds (LedgerEntrySet& view, Account const& id,
|
||||||
|
STAmount const& saDefault,
|
||||||
|
FreezeHandling freezeHandling);
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1193,6 +1193,8 @@ bool ApplicationImp::loadOldLedger (
|
|||||||
|
|
||||||
if (stp.object && (uIndex.isNonZero()))
|
if (stp.object && (uIndex.isNonZero()))
|
||||||
{
|
{
|
||||||
|
// VFALCO TODO This is the only place that
|
||||||
|
// constructor is used, try to remove it
|
||||||
STLedgerEntry sle (*stp.object, uIndex);
|
STLedgerEntry sle (*stp.object, uIndex);
|
||||||
bool ok = loadLedger->addSLE (sle);
|
bool ok = loadLedger->addSLE (sle);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
|||||||
@@ -2496,9 +2496,10 @@ Json::Value NetworkOPsImp::transJson(
|
|||||||
// If the offer create is not self funded then add the owner balance
|
// If the offer create is not self funded then add the owner balance
|
||||||
if (account != amount.issue ().account)
|
if (account != amount.issue ().account)
|
||||||
{
|
{
|
||||||
|
// VFALCO Why are we doing this hack?
|
||||||
LedgerEntrySet les (lpCurrent, tapNONE, true);
|
LedgerEntrySet les (lpCurrent, tapNONE, true);
|
||||||
auto const ownerFunds (les.accountFunds (account, amount, fhIGNORE_FREEZE));
|
auto const ownerFunds = funds(
|
||||||
|
les,account, amount, fhIGNORE_FREEZE);
|
||||||
jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText ();
|
jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2947,8 +2948,13 @@ void NetworkOPsImp::getBookPage (
|
|||||||
|
|
||||||
m_journal.trace << "getBookPage: bDirectAdvance";
|
m_journal.trace << "getBookPage: bDirectAdvance";
|
||||||
|
|
||||||
sleOfferDir = lesActive.entryCache (
|
uint256 const ledgerIndex =
|
||||||
ltDIR_NODE, lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd));
|
lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd);
|
||||||
|
if (ledgerIndex.isNonZero())
|
||||||
|
sleOfferDir = lesActive.entryCache (
|
||||||
|
ltDIR_NODE, ledgerIndex);
|
||||||
|
else
|
||||||
|
sleOfferDir.reset();
|
||||||
|
|
||||||
if (!sleOfferDir)
|
if (!sleOfferDir)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include <ripple/protocol/ErrorCodes.h>
|
#include <ripple/protocol/ErrorCodes.h>
|
||||||
#include <ripple/protocol/UintTypes.h>
|
#include <ripple/protocol/UintTypes.h>
|
||||||
#include <beast/module/core/text/LexicalCast.h>
|
#include <beast/module/core/text/LexicalCast.h>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -480,7 +480,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
|||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
|
LedgerEntrySet lesSandbox(
|
||||||
|
cache->getLedger(), tapNONE);
|
||||||
auto& sourceAccount = !isXRP (currIssuer.account)
|
auto& sourceAccount = !isXRP (currIssuer.account)
|
||||||
? currIssuer.account
|
? currIssuer.account
|
||||||
: isXRP (currIssuer.currency)
|
: isXRP (currIssuer.currency)
|
||||||
@@ -505,7 +506,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
|||||||
m_journal.debug
|
m_journal.debug
|
||||||
<< iIdentifier << " Trying with an extra path element";
|
<< iIdentifier << " Trying with an extra path element";
|
||||||
spsPaths.push_back (fullLiquidityPath);
|
spsPaths.push_back (fullLiquidityPath);
|
||||||
lesSandbox.clear();
|
reconstruct(lesSandbox, cache->getLedger (), tapNONE);
|
||||||
rc = path::RippleCalc::rippleCalculate (
|
rc = path::RippleCalc::rippleCalculate (
|
||||||
lesSandbox,
|
lesSandbox,
|
||||||
saMaxAmount,
|
saMaxAmount,
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ TER PathState::pushNode (
|
|||||||
auto const& backNode = nodes_.back ();
|
auto const& backNode = nodes_.back ();
|
||||||
if (backNode.isAccount())
|
if (backNode.isAccount())
|
||||||
{
|
{
|
||||||
auto sleRippleState = lesEntries.entryCache (
|
auto sleRippleState = lesEntries_->entryCache (
|
||||||
ltRIPPLE_STATE,
|
ltRIPPLE_STATE,
|
||||||
getRippleStateIndex (
|
getRippleStateIndex (
|
||||||
backNode.account_,
|
backNode.account_,
|
||||||
@@ -295,7 +295,7 @@ TER PathState::pushNode (
|
|||||||
<< backNode.account_ << " and " << node.account_
|
<< backNode.account_ << " and " << node.account_
|
||||||
<< " for " << node.issue_.currency << "." ;
|
<< " for " << node.issue_.currency << "." ;
|
||||||
|
|
||||||
auto sleBck = lesEntries.entryCache (
|
auto sleBck = lesEntries_->entryCache (
|
||||||
ltACCOUNT_ROOT,
|
ltACCOUNT_ROOT,
|
||||||
getAccountRootIndex (backNode.account_));
|
getAccountRootIndex (backNode.account_));
|
||||||
// Is the source account the highest numbered account ID?
|
// Is the source account the highest numbered account ID?
|
||||||
@@ -323,13 +323,13 @@ TER PathState::pushNode (
|
|||||||
|
|
||||||
if (resultCode == tesSUCCESS)
|
if (resultCode == tesSUCCESS)
|
||||||
{
|
{
|
||||||
STAmount saOwed = creditBalance (lesEntries,
|
STAmount saOwed = creditBalance (*lesEntries_,
|
||||||
node.account_, backNode.account_,
|
node.account_, backNode.account_,
|
||||||
node.issue_.currency);
|
node.issue_.currency);
|
||||||
STAmount saLimit;
|
STAmount saLimit;
|
||||||
|
|
||||||
if (saOwed <= zero) {
|
if (saOwed <= zero) {
|
||||||
saLimit = creditLimit (lesEntries,
|
saLimit = creditLimit (*lesEntries_,
|
||||||
node.account_,
|
node.account_,
|
||||||
backNode.account_,
|
backNode.account_,
|
||||||
node.issue_.currency);
|
node.issue_.currency);
|
||||||
@@ -437,7 +437,7 @@ TER PathState::expandPath (
|
|||||||
WriteLog (lsTRACE, RippleCalc)
|
WriteLog (lsTRACE, RippleCalc)
|
||||||
<< "expandPath> " << spSourcePath.getJson (0);
|
<< "expandPath> " << spSourcePath.getJson (0);
|
||||||
|
|
||||||
lesEntries = lesSource.duplicate ();
|
lesEntries_.emplace(lesSource);
|
||||||
|
|
||||||
terStatus = tesSUCCESS;
|
terStatus = tesSUCCESS;
|
||||||
|
|
||||||
@@ -632,7 +632,7 @@ void PathState::checkFreeze()
|
|||||||
// Check each order book for a global freeze
|
// Check each order book for a global freeze
|
||||||
if (nodes_[i].uFlags & STPathElement::typeIssuer)
|
if (nodes_[i].uFlags & STPathElement::typeIssuer)
|
||||||
{
|
{
|
||||||
sle = lesEntries.entryCache (ltACCOUNT_ROOT,
|
sle = lesEntries_->entryCache (ltACCOUNT_ROOT,
|
||||||
getAccountRootIndex (nodes_[i].issue_.account));
|
getAccountRootIndex (nodes_[i].issue_.account));
|
||||||
|
|
||||||
if (sle && sle->isFlag (lsfGlobalFreeze))
|
if (sle && sle->isFlag (lsfGlobalFreeze))
|
||||||
@@ -651,7 +651,7 @@ void PathState::checkFreeze()
|
|||||||
|
|
||||||
if (inAccount != outAccount)
|
if (inAccount != outAccount)
|
||||||
{
|
{
|
||||||
sle = lesEntries.entryCache (ltACCOUNT_ROOT,
|
sle = lesEntries_->entryCache (ltACCOUNT_ROOT,
|
||||||
getAccountRootIndex (outAccount));
|
getAccountRootIndex (outAccount));
|
||||||
|
|
||||||
if (sle && sle->isFlag (lsfGlobalFreeze))
|
if (sle && sle->isFlag (lsfGlobalFreeze))
|
||||||
@@ -660,7 +660,7 @@ void PathState::checkFreeze()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sle = lesEntries.entryCache (ltRIPPLE_STATE,
|
sle = lesEntries_->entryCache (ltRIPPLE_STATE,
|
||||||
getRippleStateIndex (inAccount,
|
getRippleStateIndex (inAccount,
|
||||||
outAccount, currencyID));
|
outAccount, currencyID));
|
||||||
|
|
||||||
@@ -688,9 +688,9 @@ TER PathState::checkNoRipple (
|
|||||||
Currency const& currency)
|
Currency const& currency)
|
||||||
{
|
{
|
||||||
// fetch the ripple lines into and out of this node
|
// fetch the ripple lines into and out of this node
|
||||||
SLE::pointer sleIn = lesEntries.entryCache (ltRIPPLE_STATE,
|
SLE::pointer sleIn = lesEntries_->entryCache (ltRIPPLE_STATE,
|
||||||
getRippleStateIndex (firstAccount, secondAccount, currency));
|
getRippleStateIndex (firstAccount, secondAccount, currency));
|
||||||
SLE::pointer sleOut = lesEntries.entryCache (ltRIPPLE_STATE,
|
SLE::pointer sleOut = lesEntries_->entryCache (ltRIPPLE_STATE,
|
||||||
getRippleStateIndex (secondAccount, thirdAccount, currency));
|
getRippleStateIndex (secondAccount, thirdAccount, currency));
|
||||||
|
|
||||||
if (!sleIn || !sleOut)
|
if (!sleIn || !sleOut)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <ripple/app/ledger/LedgerEntrySet.h>
|
#include <ripple/app/ledger/LedgerEntrySet.h>
|
||||||
#include <ripple/app/paths/Node.h>
|
#include <ripple/app/paths/Node.h>
|
||||||
#include <ripple/app/paths/Types.h>
|
#include <ripple/app/paths/Types.h>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -102,20 +103,37 @@ class PathState : public CountedObject <PathState>
|
|||||||
|
|
||||||
static bool lessPriority (PathState const& lhs, PathState const& rhs);
|
static bool lessPriority (PathState const& lhs, PathState const& rhs);
|
||||||
|
|
||||||
LedgerEntrySet& ledgerEntries() { return lesEntries; }
|
// VFALCO Remove or rename to view,
|
||||||
|
LedgerEntrySet& ledgerEntries()
|
||||||
|
{
|
||||||
|
return *lesEntries_;
|
||||||
|
}
|
||||||
|
|
||||||
bool isDry() const
|
bool isDry() const
|
||||||
{
|
{
|
||||||
return !(saInPass && saOutPass);
|
return !(saInPass && saOutPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TER checkNoRipple (
|
TER checkNoRipple (
|
||||||
Account const&, Account const&, Account const&, Currency const&);
|
Account const&, Account const&, Account const&, Currency const&);
|
||||||
|
|
||||||
/** Clear path structures, and clear each node. */
|
/** Clear path structures, and clear each node. */
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
TER pushNode (
|
||||||
|
int const iType,
|
||||||
|
Account const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
Account const& issuer);
|
||||||
|
|
||||||
|
TER pushImpliedNodes (
|
||||||
|
Account const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
Account const& issuer);
|
||||||
|
|
||||||
|
Json::Value getJson () const;
|
||||||
|
|
||||||
TER terStatus;
|
TER terStatus;
|
||||||
path::Node::List nodes_;
|
path::Node::List nodes_;
|
||||||
|
|
||||||
@@ -132,7 +150,7 @@ class PathState : public CountedObject <PathState>
|
|||||||
// Source may only be used there if not mentioned by an account.
|
// Source may only be used there if not mentioned by an account.
|
||||||
AccountIssueToNodeIndex umReverse;
|
AccountIssueToNodeIndex umReverse;
|
||||||
|
|
||||||
LedgerEntrySet lesEntries;
|
boost::optional<LedgerEntrySet> lesEntries_;
|
||||||
|
|
||||||
int mIndex; // Index/rank amoung siblings.
|
int mIndex; // Index/rank amoung siblings.
|
||||||
std::uint64_t uQuality; // 0 = no quality/liquity left.
|
std::uint64_t uQuality; // 0 = no quality/liquity left.
|
||||||
@@ -147,19 +165,6 @@ class PathState : public CountedObject <PathState>
|
|||||||
|
|
||||||
// If true, all liquidity on this path has been consumed.
|
// If true, all liquidity on this path has been consumed.
|
||||||
bool allLiquidityConsumed_ = false;
|
bool allLiquidityConsumed_ = false;
|
||||||
|
|
||||||
TER pushNode (
|
|
||||||
int const iType,
|
|
||||||
Account const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
Account const& issuer);
|
|
||||||
|
|
||||||
TER pushImpliedNodes (
|
|
||||||
Account const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
Account const& issuer);
|
|
||||||
|
|
||||||
Json::Value getJson () const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -288,7 +288,9 @@ TER RippleCalc::rippleCalculate ()
|
|||||||
assert (mActiveLedger.isValid ());
|
assert (mActiveLedger.isValid ());
|
||||||
mActiveLedger.swapWith (pathState->ledgerEntries());
|
mActiveLedger.swapWith (pathState->ledgerEntries());
|
||||||
// For the path, save ledger state.
|
// For the path, save ledger state.
|
||||||
mActiveLedger.invalidate ();
|
|
||||||
|
// VFALCO Can this be done without the function call?
|
||||||
|
mActiveLedger.deprecatedInvalidate();
|
||||||
|
|
||||||
iBest = pathState->index ();
|
iBest = pathState->index ();
|
||||||
}
|
}
|
||||||
@@ -339,7 +341,10 @@ TER RippleCalc::rippleCalculate ()
|
|||||||
// return.
|
// return.
|
||||||
assert (pathState->ledgerEntries().isValid ());
|
assert (pathState->ledgerEntries().isValid ());
|
||||||
mActiveLedger.swapWith (pathState->ledgerEntries());
|
mActiveLedger.swapWith (pathState->ledgerEntries());
|
||||||
pathState->ledgerEntries().invalidate ();
|
|
||||||
|
// VFALCO Why is this needed? Can it be done
|
||||||
|
// without the function call?
|
||||||
|
pathState->ledgerEntries().deprecatedInvalidate();
|
||||||
|
|
||||||
actualAmountIn_ += pathState->inPass();
|
actualAmountIn_ += pathState->inPass();
|
||||||
actualAmountOut_ += pathState->outPass();
|
actualAmountOut_ += pathState->outPass();
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
|
|||||||
= node().sleOffer->getFieldAmount (sfTakerGets);
|
= node().sleOffer->getFieldAmount (sfTakerGets);
|
||||||
|
|
||||||
// Funds left.
|
// Funds left.
|
||||||
node().saOfferFunds = ledger().accountFunds (
|
node().saOfferFunds = funds (ledger(),
|
||||||
node().offerOwnerAccount_,
|
node().offerOwnerAccount_,
|
||||||
node().saTakerGets,
|
node().saTakerGets,
|
||||||
fhZERO_IF_FROZEN);
|
fhZERO_IF_FROZEN);
|
||||||
@@ -329,7 +329,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
|
|||||||
|
|
||||||
// Only the current node is allowed to use the source.
|
// Only the current node is allowed to use the source.
|
||||||
|
|
||||||
node().saOfferFunds = ledger().accountFunds (
|
node().saOfferFunds = funds(ledger(),
|
||||||
node().offerOwnerAccount_,
|
node().offerOwnerAccount_,
|
||||||
node().saTakerGets,
|
node().saTakerGets,
|
||||||
fhZERO_IF_FROZEN);
|
fhZERO_IF_FROZEN);
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const
|
|||||||
TER resultCode = tecPATH_DRY;
|
TER resultCode = tecPATH_DRY;
|
||||||
PathCursor pc = *this;
|
PathCursor pc = *this;
|
||||||
|
|
||||||
ledger() = lesCheckpoint.duplicate ();
|
// duplicate
|
||||||
|
reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint);
|
||||||
|
|
||||||
for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; )
|
for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; )
|
||||||
{
|
{
|
||||||
WriteLog (lsTRACE, RippleCalc)
|
WriteLog (lsTRACE, RippleCalc)
|
||||||
@@ -59,7 +61,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const
|
|||||||
return resultCode;
|
return resultCode;
|
||||||
|
|
||||||
// Do forward.
|
// Do forward.
|
||||||
ledger() = lesCheckpoint.duplicate ();
|
// duplicate
|
||||||
|
reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint);
|
||||||
|
|
||||||
for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_)
|
for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_)
|
||||||
{
|
{
|
||||||
WriteLog (lsTRACE, RippleCalc)
|
WriteLog (lsTRACE, RippleCalc)
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
PathCursor(PathCursor const&) = default;
|
PathCursor(PathCursor const&) = default;
|
||||||
|
|
||||||
PathCursor increment(int delta = 1) const {
|
PathCursor increment(int delta = 1) const
|
||||||
|
{
|
||||||
return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta};
|
return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,11 +91,6 @@ private:
|
|||||||
STAmount& saInAct,
|
STAmount& saInAct,
|
||||||
STAmount& saInFees) const;
|
STAmount& saInFees) const;
|
||||||
|
|
||||||
RippleCalc& rippleCalc_;
|
|
||||||
PathState& pathState_;
|
|
||||||
bool multiQuality_;
|
|
||||||
NodeIndex nodeIndex_;
|
|
||||||
|
|
||||||
LedgerEntrySet& ledger() const
|
LedgerEntrySet& ledger() const
|
||||||
{
|
{
|
||||||
return rippleCalc_.mActiveLedger;
|
return rippleCalc_.mActiveLedger;
|
||||||
@@ -129,6 +125,11 @@ private:
|
|||||||
{
|
{
|
||||||
return node (restrict (nodeIndex_ + 1));
|
return node (restrict (nodeIndex_ + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RippleCalc& rippleCalc_;
|
||||||
|
PathState& pathState_;
|
||||||
|
bool multiQuality_;
|
||||||
|
NodeIndex nodeIndex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // path
|
} // path
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class AccountInfo
|
|||||||
private:
|
private:
|
||||||
Account account_;
|
Account account_;
|
||||||
std::shared_ptr<Ledger> ledger_;
|
std::shared_ptr<Ledger> ledger_;
|
||||||
boost::optional<SLE const> root_;
|
std::shared_ptr<SLE const> root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AccountInfo(Account const& account,
|
AccountInfo(Account const& account,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <ripple/app/ledger/Ledger.h>
|
#include <ripple/app/ledger/Ledger.h>
|
||||||
#include <ripple/app/ledger/LedgerEntrySet.h>
|
#include <ripple/app/ledger/LedgerEntrySet.h>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -35,11 +36,7 @@ static multisign_t const multisign;
|
|||||||
// One instance per ledger.
|
// One instance per ledger.
|
||||||
// Only one transaction applied at a time.
|
// Only one transaction applied at a time.
|
||||||
class TransactionEngine
|
class TransactionEngine
|
||||||
: public CountedObject <TransactionEngine>
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
static char const* getCountedObjectName () { return "TransactionEngine"; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool enableMultiSign_ =
|
bool enableMultiSign_ =
|
||||||
#if RIPPLE_ENABLE_MULTI_SIGN
|
#if RIPPLE_ENABLE_MULTI_SIGN
|
||||||
@@ -48,17 +45,16 @@ private:
|
|||||||
false;
|
false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LedgerEntrySet mNodes;
|
boost::optional<LedgerEntrySet> mNodes;
|
||||||
|
|
||||||
void txnWrite ();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Ledger::pointer mLedger;
|
Ledger::pointer mLedger;
|
||||||
int mTxnSeq = 0;
|
int mTxnSeq = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionEngine () = default;
|
TransactionEngine() = default;
|
||||||
|
|
||||||
|
explicit
|
||||||
TransactionEngine (Ledger::ref ledger)
|
TransactionEngine (Ledger::ref ledger)
|
||||||
: mLedger (ledger)
|
: mLedger (ledger)
|
||||||
{
|
{
|
||||||
@@ -81,7 +77,7 @@ public:
|
|||||||
LedgerEntrySet&
|
LedgerEntrySet&
|
||||||
view ()
|
view ()
|
||||||
{
|
{
|
||||||
return mNodes;
|
return *mNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::ref
|
Ledger::ref
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ public:
|
|||||||
if (!sleTicket)
|
if (!sleTicket)
|
||||||
return tecNO_ENTRY;
|
return tecNO_ENTRY;
|
||||||
|
|
||||||
Account const ticket_owner (sleTicket->getFieldAccount160 (sfAccount));
|
auto const ticket_owner =
|
||||||
|
sleTicket->getFieldAccount160 (sfAccount);
|
||||||
|
|
||||||
bool authorized (mTxnAccountID == ticket_owner);
|
bool authorized =
|
||||||
|
mTxnAccountID == ticket_owner;
|
||||||
|
|
||||||
// The target can also always remove a ticket
|
// The target can also always remove a ticket
|
||||||
if (!authorized && sleTicket->isFieldPresent (sfTarget))
|
if (!authorized && sleTicket->isFieldPresent (sfTarget))
|
||||||
@@ -77,7 +79,8 @@ public:
|
|||||||
TER const result = mEngine->view ().dirDelete (false, hint,
|
TER const result = mEngine->view ().dirDelete (false, hint,
|
||||||
getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0));
|
getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0));
|
||||||
|
|
||||||
mEngine->view ().decrementOwnerCount (ticket_owner);
|
adjustOwnerCount(mEngine->view(), mEngine->view().entryCache(
|
||||||
|
ltACCOUNT_ROOT, getAccountRootIndex(ticket_owner)), -1);
|
||||||
mEngine->view ().entryDelete (sleTicket);
|
mEngine->view ().entryDelete (sleTicket);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -122,15 +122,18 @@ private:
|
|||||||
SLE::pointer amendmentObject (mEngine->view().entryCache (ltAMENDMENTS, index));
|
SLE::pointer amendmentObject (mEngine->view().entryCache (ltAMENDMENTS, index));
|
||||||
|
|
||||||
if (!amendmentObject)
|
if (!amendmentObject)
|
||||||
amendmentObject = mEngine->view().entryCreate(ltAMENDMENTS, index);
|
{
|
||||||
|
amendmentObject = std::make_shared<SLE>(
|
||||||
|
ltAMENDMENTS, index);
|
||||||
|
mEngine->view().entryCreate(amendmentObject);
|
||||||
|
}
|
||||||
|
|
||||||
STVector256 amendments (amendmentObject->getFieldV256 (sfAmendments));
|
STVector256 amendments =
|
||||||
|
amendmentObject->getFieldV256(sfAmendments);
|
||||||
|
|
||||||
if (std::find (amendments.begin(), amendments.end(),
|
if (std::find (amendments.begin(), amendments.end(),
|
||||||
amendment) != amendments.end ())
|
amendment) != amendments.end ())
|
||||||
{
|
|
||||||
return tefALREADY;
|
return tefALREADY;
|
||||||
}
|
|
||||||
|
|
||||||
amendments.push_back (amendment);
|
amendments.push_back (amendment);
|
||||||
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
||||||
@@ -151,7 +154,11 @@ private:
|
|||||||
SLE::pointer feeObject = mEngine->view().entryCache (ltFEE_SETTINGS, index);
|
SLE::pointer feeObject = mEngine->view().entryCache (ltFEE_SETTINGS, index);
|
||||||
|
|
||||||
if (!feeObject)
|
if (!feeObject)
|
||||||
feeObject = mEngine->view().entryCreate (ltFEE_SETTINGS, index);
|
{
|
||||||
|
feeObject = std::make_shared<SLE>(
|
||||||
|
ltFEE_SETTINGS, index);
|
||||||
|
mEngine->view().entryCreate(feeObject);
|
||||||
|
}
|
||||||
|
|
||||||
// VFALCO-FIXME this generates errors
|
// VFALCO-FIXME this generates errors
|
||||||
// m_journal.trace <<
|
// m_journal.trace <<
|
||||||
|
|||||||
@@ -101,11 +101,9 @@ private:
|
|||||||
{
|
{
|
||||||
if (offer.fully_consumed ())
|
if (offer.fully_consumed ())
|
||||||
return true;
|
return true;
|
||||||
|
auto const amount = funds(view, offer.owner(),
|
||||||
auto const funds (view.accountFunds (offer.owner(),
|
offer.amount().out, fhZERO_IF_FROZEN);
|
||||||
offer.amount().out, fhZERO_IF_FROZEN));
|
return (amount <= zero);
|
||||||
|
|
||||||
return (funds <= zero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -202,7 +200,7 @@ private:
|
|||||||
m_journal.debug << " in: " << offers_direct.tip ().amount().in;
|
m_journal.debug << " in: " << offers_direct.tip ().amount().in;
|
||||||
m_journal.debug << " out: " << offers_direct.tip ().amount ().out;
|
m_journal.debug << " out: " << offers_direct.tip ().amount ().out;
|
||||||
m_journal.debug << " owner: " << offers_direct.tip ().owner ();
|
m_journal.debug << " owner: " << offers_direct.tip ().owner ();
|
||||||
m_journal.debug << " funds: " << view.accountFunds (
|
m_journal.debug << " funds: " << funds(view,
|
||||||
offers_direct.tip ().owner (),
|
offers_direct.tip ().owner (),
|
||||||
offers_direct.tip ().amount ().out,
|
offers_direct.tip ().amount ().out,
|
||||||
fhIGNORE_FREEZE);
|
fhIGNORE_FREEZE);
|
||||||
@@ -222,12 +220,12 @@ private:
|
|||||||
{
|
{
|
||||||
if (m_journal.debug)
|
if (m_journal.debug)
|
||||||
{
|
{
|
||||||
auto const owner1_funds_before = view.accountFunds (
|
auto const owner1_funds_before = funds(view,
|
||||||
offers_leg1.tip ().owner (),
|
offers_leg1.tip ().owner (),
|
||||||
offers_leg1.tip ().amount ().out,
|
offers_leg1.tip ().amount ().out,
|
||||||
fhIGNORE_FREEZE);
|
fhIGNORE_FREEZE);
|
||||||
|
|
||||||
auto const owner2_funds_before = view.accountFunds (
|
auto const owner2_funds_before = funds(view,
|
||||||
offers_leg2.tip ().owner (),
|
offers_leg2.tip ().owner (),
|
||||||
offers_leg2.tip ().amount ().out,
|
offers_leg2.tip ().amount ().out,
|
||||||
fhIGNORE_FREEZE);
|
fhIGNORE_FREEZE);
|
||||||
@@ -321,7 +319,7 @@ private:
|
|||||||
m_journal.debug << " in: " << offer.amount ().in;
|
m_journal.debug << " in: " << offer.amount ().in;
|
||||||
m_journal.debug << " out: " << offer.amount ().out;
|
m_journal.debug << " out: " << offer.amount ().out;
|
||||||
m_journal.debug << " owner: " << offer.owner ();
|
m_journal.debug << " owner: " << offer.owner ();
|
||||||
m_journal.debug << " funds: " << view.accountFunds (
|
m_journal.debug << " funds: " << funds(view,
|
||||||
offer.owner (), offer.amount ().out, fhIGNORE_FREEZE);
|
offer.owner (), offer.amount ().out, fhIGNORE_FREEZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,7 +602,7 @@ public:
|
|||||||
|
|
||||||
result = tecFROZEN;
|
result = tecFROZEN;
|
||||||
}
|
}
|
||||||
else if (view.accountFunds (
|
else if (funds(view,
|
||||||
mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN) <= zero)
|
mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN) <= zero)
|
||||||
{
|
{
|
||||||
if (m_journal.debug) m_journal.debug <<
|
if (m_journal.debug) m_journal.debug <<
|
||||||
@@ -795,7 +793,7 @@ public:
|
|||||||
if (result == tesSUCCESS)
|
if (result == tesSUCCESS)
|
||||||
{
|
{
|
||||||
// Update owner count.
|
// Update owner count.
|
||||||
view.incrementOwnerCount (sleCreator);
|
adjustOwnerCount(view, sleCreator, 1);
|
||||||
|
|
||||||
if (m_journal.trace) m_journal.trace <<
|
if (m_journal.trace) m_journal.trace <<
|
||||||
"adding to book: " << to_string (saTakerPays.issue ()) <<
|
"adding to book: " << to_string (saTakerPays.issue ()) <<
|
||||||
@@ -818,8 +816,7 @@ public:
|
|||||||
|
|
||||||
if (result == tesSUCCESS)
|
if (result == tesSUCCESS)
|
||||||
{
|
{
|
||||||
SLE::pointer sleOffer (mEngine->view().entryCreate (ltOFFER, offer_index));
|
auto sleOffer = std::make_shared<SLE>(ltOFFER, offer_index);
|
||||||
|
|
||||||
sleOffer->setFieldAccount (sfAccount, mTxnAccountID);
|
sleOffer->setFieldAccount (sfAccount, mTxnAccountID);
|
||||||
sleOffer->setFieldU32 (sfSequence, uSequence);
|
sleOffer->setFieldU32 (sfSequence, uSequence);
|
||||||
sleOffer->setFieldH256 (sfBookDirectory, uDirectory);
|
sleOffer->setFieldH256 (sfBookDirectory, uDirectory);
|
||||||
@@ -827,15 +824,13 @@ public:
|
|||||||
sleOffer->setFieldAmount (sfTakerGets, saTakerGets);
|
sleOffer->setFieldAmount (sfTakerGets, saTakerGets);
|
||||||
sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode);
|
sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode);
|
||||||
sleOffer->setFieldU64 (sfBookNode, uBookNode);
|
sleOffer->setFieldU64 (sfBookNode, uBookNode);
|
||||||
|
|
||||||
if (uExpiration)
|
if (uExpiration)
|
||||||
sleOffer->setFieldU32 (sfExpiration, uExpiration);
|
sleOffer->setFieldU32 (sfExpiration, uExpiration);
|
||||||
|
|
||||||
if (bPassive)
|
if (bPassive)
|
||||||
sleOffer->setFlag (lsfPassive);
|
sleOffer->setFlag (lsfPassive);
|
||||||
|
|
||||||
if (bSell)
|
if (bSell)
|
||||||
sleOffer->setFlag (lsfSell);
|
sleOffer->setFlag (lsfSell);
|
||||||
|
mEngine->view().entryCreate(sleOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != tesSUCCESS)
|
if (result != tesSUCCESS)
|
||||||
|
|||||||
@@ -85,14 +85,13 @@ public:
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLE::pointer sleTicket = mEngine->view().entryCreate (ltTICKET,
|
SLE::pointer sleTicket = std::make_shared<SLE>(ltTICKET,
|
||||||
getTicketIndex (mTxnAccountID, mTxn.getSequence ()));
|
getTicketIndex (mTxnAccountID, mTxn.getSequence ()));
|
||||||
|
|
||||||
sleTicket->setFieldAccount (sfAccount, mTxnAccountID);
|
sleTicket->setFieldAccount (sfAccount, mTxnAccountID);
|
||||||
sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ());
|
sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ());
|
||||||
|
|
||||||
if (expiration != 0)
|
if (expiration != 0)
|
||||||
sleTicket->setFieldU32 (sfExpiration, expiration);
|
sleTicket->setFieldU32 (sfExpiration, expiration);
|
||||||
|
mEngine->view().entryCreate (sleTicket);
|
||||||
|
|
||||||
if (mTxn.isFieldPresent (sfTarget))
|
if (mTxn.isFieldPresent (sfTarget))
|
||||||
{
|
{
|
||||||
@@ -134,7 +133,7 @@ public:
|
|||||||
sleTicket->setFieldU64(sfOwnerNode, hint);
|
sleTicket->setFieldU64(sfOwnerNode, hint);
|
||||||
|
|
||||||
// If we succeeded, the new entry counts agains the creator's reserve.
|
// If we succeeded, the new entry counts agains the creator's reserve.
|
||||||
mEngine->view ().incrementOwnerCount (mTxnAccount);
|
adjustOwnerCount(mEngine->view(), mTxnAccount, 1);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <BeastConfig.h>
|
#include <BeastConfig.h>
|
||||||
#include <ripple/app/tx/LocalTxs.h>
|
#include <ripple/app/tx/LocalTxs.h>
|
||||||
|
#include <ripple/app/main/Application.h>
|
||||||
#include <ripple/app/misc/CanonicalTXSet.h>
|
#include <ripple/app/misc/CanonicalTXSet.h>
|
||||||
#include <ripple/protocol/Indexes.h>
|
#include <ripple/protocol/Indexes.h>
|
||||||
|
|
||||||
@@ -125,8 +126,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
if (ledger->hasTransaction (txn.getID ()))
|
if (ledger->hasTransaction (txn.getID ()))
|
||||||
return true;
|
return true;
|
||||||
auto const sle = ledger->fetch(
|
auto const sle = fetch(*ledger,
|
||||||
getAccountRootIndex(txn.getAccount()));
|
getAccountRootIndex(txn.getAccount().getAccountID()),
|
||||||
|
getApp().getSLECache());
|
||||||
if (! sle)
|
if (! sle)
|
||||||
return false;
|
return false;
|
||||||
if (sle->getFieldU32 (sfSequence) > txn.getSeq ())
|
if (sle->getFieldU32 (sfSequence) > txn.getSeq ())
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ OfferStream::step ()
|
|||||||
// Calculate owner funds
|
// Calculate owner funds
|
||||||
// NIKB NOTE The calling code also checks the funds, how expensive is
|
// NIKB NOTE The calling code also checks the funds, how expensive is
|
||||||
// looking up the funds twice?
|
// looking up the funds twice?
|
||||||
STAmount const owner_funds (view().accountFunds (
|
auto const owner_funds = funds(view(),
|
||||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN));
|
m_offer.owner(), amount.out, fhZERO_IF_FROZEN);
|
||||||
|
|
||||||
// Check for unfunded offer
|
// Check for unfunded offer
|
||||||
if (owner_funds <= zero)
|
if (owner_funds <= zero)
|
||||||
@@ -131,7 +131,7 @@ OfferStream::step ()
|
|||||||
// If the owner's balance in the pristine view is the same,
|
// If the owner's balance in the pristine view is the same,
|
||||||
// we haven't modified the balance and therefore the
|
// we haven't modified the balance and therefore the
|
||||||
// offer is "found unfunded" versus "became unfunded"
|
// offer is "found unfunded" versus "became unfunded"
|
||||||
auto const original_funds = view_cancel().accountFunds (
|
auto const original_funds = funds(view_cancel(),
|
||||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN);
|
m_offer.owner(), amount.out, fhZERO_IF_FROZEN);
|
||||||
|
|
||||||
if (original_funds == owner_funds)
|
if (original_funds == owner_funds)
|
||||||
|
|||||||
@@ -233,10 +233,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the account.
|
// Create the account.
|
||||||
auto const newIndex = getAccountRootIndex (uDstAccountID);
|
sleDst = std::make_shared<SLE>(ltACCOUNT_ROOT,
|
||||||
sleDst = mEngine->view().entryCreate (ltACCOUNT_ROOT, newIndex);
|
getAccountRootIndex (uDstAccountID));
|
||||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||||
sleDst->setFieldU32 (sfSequence, 1);
|
sleDst->setFieldU32 (sfSequence, 1);
|
||||||
|
mEngine->view().entryCreate(sleDst);
|
||||||
}
|
}
|
||||||
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
||||||
!mTxn.isFieldPresent (sfDestinationTag))
|
!mTxn.isFieldPresent (sfDestinationTag))
|
||||||
|
|||||||
@@ -234,8 +234,8 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
|||||||
return tecINSUFFICIENT_RESERVE;
|
return tecINSUFFICIENT_RESERVE;
|
||||||
|
|
||||||
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
|
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
|
||||||
SLE::pointer signerList (
|
auto signerList = std::make_shared<SLE>(ltSIGNER_LIST, index);
|
||||||
mEngine->view().entryCreate (ltSIGNER_LIST, index));
|
mEngine->view().entryCreate (signerList);
|
||||||
writeSignersToLedger (signerList);
|
writeSignersToLedger (signerList);
|
||||||
|
|
||||||
// Lambda for call to dirAdd.
|
// Lambda for call to dirAdd.
|
||||||
@@ -259,7 +259,8 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
|||||||
signerList->setFieldU64 (sfOwnerNode, hint);
|
signerList->setFieldU64 (sfOwnerNode, hint);
|
||||||
|
|
||||||
// If we succeeded, the new entry counts against the creator's reserve.
|
// If we succeeded, the new entry counts against the creator's reserve.
|
||||||
mEngine->view ().increaseOwnerCount (mTxnAccount, addedOwnerCount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
mTxnAccount, addedOwnerCount);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -295,13 +296,17 @@ SetSignerList::destroySignerList (uint256 const& index)
|
|||||||
getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0));
|
getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0));
|
||||||
|
|
||||||
if (result == tesSUCCESS)
|
if (result == tesSUCCESS)
|
||||||
mEngine->view ().decreaseOwnerCount (mTxnAccount, removeFromOwnerCount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
mTxnAccount, removeFromOwnerCount);
|
||||||
|
|
||||||
mEngine->view ().entryDelete (signerList);
|
mEngine->view ().entryDelete (signerList);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VFALCO NOTE This name is misleading, the signers
|
||||||
|
// are not written to the ledger they are
|
||||||
|
// added to the SLE.
|
||||||
void
|
void
|
||||||
SetSignerList::writeSignersToLedger (SLE::pointer ledgerEntry)
|
SetSignerList::writeSignersToLedger (SLE::pointer ledgerEntry)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -339,7 +339,8 @@ public:
|
|||||||
if (bLowReserveSet && !bLowReserved)
|
if (bLowReserveSet && !bLowReserved)
|
||||||
{
|
{
|
||||||
// Set reserve for low account.
|
// Set reserve for low account.
|
||||||
mEngine->view ().incrementOwnerCount (sleLowAccount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
sleLowAccount, 1);
|
||||||
uFlagsOut |= lsfLowReserve;
|
uFlagsOut |= lsfLowReserve;
|
||||||
|
|
||||||
if (!bHigh)
|
if (!bHigh)
|
||||||
@@ -349,14 +350,16 @@ public:
|
|||||||
if (bLowReserveClear && bLowReserved)
|
if (bLowReserveClear && bLowReserved)
|
||||||
{
|
{
|
||||||
// Clear reserve for low account.
|
// Clear reserve for low account.
|
||||||
mEngine->view ().decrementOwnerCount (sleLowAccount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
sleLowAccount, -1);
|
||||||
uFlagsOut &= ~lsfLowReserve;
|
uFlagsOut &= ~lsfLowReserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bHighReserveSet && !bHighReserved)
|
if (bHighReserveSet && !bHighReserved)
|
||||||
{
|
{
|
||||||
// Set reserve for high account.
|
// Set reserve for high account.
|
||||||
mEngine->view ().incrementOwnerCount (sleHighAccount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
sleHighAccount, 1);
|
||||||
uFlagsOut |= lsfHighReserve;
|
uFlagsOut |= lsfHighReserve;
|
||||||
|
|
||||||
if (bHigh)
|
if (bHigh)
|
||||||
@@ -366,7 +369,8 @@ public:
|
|||||||
if (bHighReserveClear && bHighReserved)
|
if (bHighReserveClear && bHighReserved)
|
||||||
{
|
{
|
||||||
// Clear reserve for high account.
|
// Clear reserve for high account.
|
||||||
mEngine->view ().decrementOwnerCount (sleHighAccount);
|
adjustOwnerCount(mEngine->view(),
|
||||||
|
sleHighAccount, -1);
|
||||||
uFlagsOut &= ~lsfHighReserve;
|
uFlagsOut &= ~lsfHighReserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -581,9 +581,9 @@ Taker::consume_offer (Offer const& offer, Amounts const& order)
|
|||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
Taker::get_funds (Account const& account, STAmount const& funds) const
|
Taker::get_funds (Account const& account, STAmount const& amount) const
|
||||||
{
|
{
|
||||||
return view_.accountFunds (account, funds, fhZERO_IF_FROZEN);
|
return funds(view_, account, amount, fhZERO_IF_FROZEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER Taker::transfer_xrp (
|
TER Taker::transfer_xrp (
|
||||||
|
|||||||
@@ -31,53 +31,6 @@ namespace ripple {
|
|||||||
// XXX Make sure all fields are recognized in transactions.
|
// XXX Make sure all fields are recognized in transactions.
|
||||||
//
|
//
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
case taaNONE:
|
|
||||||
assert (false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case taaCACHED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case taaCREATE:
|
|
||||||
{
|
|
||||||
// VFALCO Is this logging necessary anymore?
|
|
||||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
|
||||||
"applyTransaction: taaCREATE: " << sleEntry->getText ();
|
|
||||||
mLedger->insert(*sleEntry);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case taaMODIFY:
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
|
||||||
"applyTransaction: taaMODIFY: " << sleEntry->getText ();
|
|
||||||
mLedger->replace(*sleEntry);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case taaDELETE:
|
|
||||||
{
|
|
||||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
|
||||||
"applyTransaction: taaDELETE: " << sleEntry->getText ();
|
|
||||||
mLedger->erase(it.first);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<TER, bool>
|
std::pair<TER, bool>
|
||||||
TransactionEngine::applyTransaction (
|
TransactionEngine::applyTransaction (
|
||||||
STTx const& txn,
|
STTx const& txn,
|
||||||
@@ -96,7 +49,8 @@ TransactionEngine::applyTransaction (
|
|||||||
return std::make_pair(temINVALID_FLAG, false);
|
return std::make_pair(temINVALID_FLAG, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNodes.init (mLedger, txID, mLedger->getLedgerSeq (), params);
|
mNodes.emplace(mLedger, txID,
|
||||||
|
mLedger->getLedgerSeq(), params);
|
||||||
|
|
||||||
#ifdef BEAST_DEBUG
|
#ifdef BEAST_DEBUG
|
||||||
if (1)
|
if (1)
|
||||||
@@ -146,9 +100,10 @@ TransactionEngine::applyTransaction (
|
|||||||
// only claim the transaction fee
|
// only claim the transaction fee
|
||||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
WriteLog (lsDEBUG, TransactionEngine) <<
|
||||||
"Reprocessing tx " << txID << " to only claim fee";
|
"Reprocessing tx " << txID << " to only claim fee";
|
||||||
mNodes.clear ();
|
mNodes.emplace(mLedger, txID,
|
||||||
|
mLedger->getLedgerSeq(), params);
|
||||||
|
|
||||||
SLE::pointer txnAcct = mNodes.entryCache (ltACCOUNT_ROOT,
|
SLE::pointer txnAcct = mNodes->entryCache (ltACCOUNT_ROOT,
|
||||||
getAccountRootIndex (txn.getSourceAccount ()));
|
getAccountRootIndex (txn.getSourceAccount ()));
|
||||||
|
|
||||||
if (!txnAcct)
|
if (!txnAcct)
|
||||||
@@ -182,7 +137,7 @@ TransactionEngine::applyTransaction (
|
|||||||
fee = balance;
|
fee = balance;
|
||||||
txnAcct->setFieldAmount (sfBalance, balance - fee);
|
txnAcct->setFieldAmount (sfBalance, balance - fee);
|
||||||
txnAcct->setFieldU32 (sfSequence, t_seq + 1);
|
txnAcct->setFieldU32 (sfSequence, t_seq + 1);
|
||||||
mNodes.entryModify (txnAcct);
|
mNodes->entryModify (txnAcct);
|
||||||
didApply = true;
|
didApply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +157,7 @@ TransactionEngine::applyTransaction (
|
|||||||
WriteLog (lsFATAL, TransactionEngine) <<
|
WriteLog (lsFATAL, TransactionEngine) <<
|
||||||
transToken (terResult) << ": " << transHuman (terResult);
|
transToken (terResult) << ": " << transHuman (terResult);
|
||||||
WriteLog (lsFATAL, TransactionEngine) <<
|
WriteLog (lsFATAL, TransactionEngine) <<
|
||||||
mNodes.getJson (0);
|
mNodes->getJson (0);
|
||||||
didApply = false;
|
didApply = false;
|
||||||
terResult = tefINTERNAL;
|
terResult = tefINTERNAL;
|
||||||
}
|
}
|
||||||
@@ -212,9 +167,10 @@ TransactionEngine::applyTransaction (
|
|||||||
// Transaction succeeded fully or (retries are not allowed and the
|
// Transaction succeeded fully or (retries are not allowed and the
|
||||||
// transaction could claim a fee)
|
// transaction could claim a fee)
|
||||||
Serializer m;
|
Serializer m;
|
||||||
mNodes.calcRawMeta (m, terResult, mTxnSeq++);
|
mNodes->calcRawMeta (m, terResult, mTxnSeq++);
|
||||||
|
|
||||||
txnWrite ();
|
assert(mLedger == mNodes->getLedger());
|
||||||
|
mNodes->apply();
|
||||||
|
|
||||||
Serializer s;
|
Serializer s;
|
||||||
txn.add (s);
|
txn.add (s);
|
||||||
@@ -253,7 +209,7 @@ TransactionEngine::applyTransaction (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mNodes.clear ();
|
mNodes = boost::none;
|
||||||
|
|
||||||
if (!(params & tapOPEN_LEDGER) && isTemMalformed (terResult))
|
if (!(params & tapOPEN_LEDGER) && isTemMalformed (terResult))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,11 +21,13 @@
|
|||||||
#define RIPPLE_PROTOCOL_INDEXES_H_INCLUDED
|
#define RIPPLE_PROTOCOL_INDEXES_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/protocol/LedgerFormats.h>
|
#include <ripple/protocol/LedgerFormats.h>
|
||||||
|
#include <ripple/protocol/Protocol.h>
|
||||||
#include <ripple/protocol/RippleAddress.h>
|
#include <ripple/protocol/RippleAddress.h>
|
||||||
#include <ripple/protocol/Serializer.h>
|
#include <ripple/protocol/Serializer.h>
|
||||||
#include <ripple/protocol/UintTypes.h>
|
#include <ripple/protocol/UintTypes.h>
|
||||||
#include <ripple/basics/base_uint.h>
|
#include <ripple/basics/base_uint.h>
|
||||||
#include <ripple/protocol/Book.h>
|
#include <ripple/protocol/Book.h>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -89,6 +91,137 @@ getRippleStateIndex (Account const& a, Issue const& issue);
|
|||||||
|
|
||||||
uint256
|
uint256
|
||||||
getSignerListIndex (Account const& account);
|
getSignerListIndex (Account const& account);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** A pair of SHAMap key and LedgerEntryType.
|
||||||
|
|
||||||
|
A Keylet identifies both a key in the state map
|
||||||
|
and its ledger entry type.
|
||||||
|
*/
|
||||||
|
struct Keylet
|
||||||
|
{
|
||||||
|
LedgerEntryType type;
|
||||||
|
uint256 key;
|
||||||
|
|
||||||
|
Keylet (LedgerEntryType type_,
|
||||||
|
uint256 const& key_)
|
||||||
|
: type(type_)
|
||||||
|
, key(key_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Keylet computation funclets. */
|
||||||
|
namespace keylet {
|
||||||
|
|
||||||
|
/** Account root */
|
||||||
|
struct account_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id) const;
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
|
Keylet operator()(RippleAddress const& ra) const;
|
||||||
|
};
|
||||||
|
static account_t const account {};
|
||||||
|
|
||||||
|
/** OWner directory */
|
||||||
|
struct owndir_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id) const;
|
||||||
|
};
|
||||||
|
static owndir_t const ownerDir {};
|
||||||
|
|
||||||
|
/** Skip list */
|
||||||
|
struct skip_t
|
||||||
|
{
|
||||||
|
Keylet operator()() const;
|
||||||
|
|
||||||
|
Keylet operator()(LedgerIndex ledger) const;
|
||||||
|
};
|
||||||
|
static skip_t const skip {};
|
||||||
|
|
||||||
|
/** The amendment table */
|
||||||
|
struct amendments_t
|
||||||
|
{
|
||||||
|
Keylet operator()() const;
|
||||||
|
};
|
||||||
|
static amendments_t const amendments {};
|
||||||
|
|
||||||
|
/** The ledger fees */
|
||||||
|
struct fee_t
|
||||||
|
{
|
||||||
|
Keylet operator()() const;
|
||||||
|
};
|
||||||
|
static fee_t const fee {};
|
||||||
|
|
||||||
|
/** The beginning of an order book */
|
||||||
|
struct book_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Book const& b) const;
|
||||||
|
};
|
||||||
|
static book_t const book {};
|
||||||
|
|
||||||
|
/** An offer from an account */
|
||||||
|
struct offer_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id,
|
||||||
|
std::uint32_t seq) const;
|
||||||
|
};
|
||||||
|
static offer_t const offer {};
|
||||||
|
|
||||||
|
/** An item in a directory */
|
||||||
|
struct item_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Keylet const& k,
|
||||||
|
std::uint64_t index,
|
||||||
|
LedgerEntryType type) const;
|
||||||
|
};
|
||||||
|
static item_t const item {};
|
||||||
|
|
||||||
|
/** The directory for a specific quality */
|
||||||
|
struct quality_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Keylet const& k,
|
||||||
|
std::uint64_t q) const;
|
||||||
|
};
|
||||||
|
static quality_t const quality {};
|
||||||
|
|
||||||
|
/** The directry for the next lower quality */
|
||||||
|
struct next_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Keylet const& k) const;
|
||||||
|
};
|
||||||
|
static next_t const next {};
|
||||||
|
|
||||||
|
/** A ticket belonging to an account */
|
||||||
|
struct ticket_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id,
|
||||||
|
std::uint32_t seq) const;
|
||||||
|
};
|
||||||
|
static ticket_t const ticket {};
|
||||||
|
|
||||||
|
/** A trust line */
|
||||||
|
struct trust_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id0,
|
||||||
|
Account const& id1, Currency const& currency) const;
|
||||||
|
|
||||||
|
Keylet operator()(Account const& id,
|
||||||
|
Issue const& issue) const;
|
||||||
|
};
|
||||||
|
static trust_t const trust {};
|
||||||
|
|
||||||
|
/** A SignerList */
|
||||||
|
struct signers_t
|
||||||
|
{
|
||||||
|
Keylet operator()(Account const& id) const;
|
||||||
|
};
|
||||||
|
static signers_t const signers {};
|
||||||
|
|
||||||
|
} // keylet
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED
|
#ifndef RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED
|
||||||
#define RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED
|
#define RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/protocol/LedgerFormats.h>
|
#include <ripple/protocol/Indexes.h>
|
||||||
#include <ripple/protocol/STObject.h>
|
#include <ripple/protocol/STObject.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -35,10 +35,21 @@ public:
|
|||||||
using pointer = std::shared_ptr<STLedgerEntry>;
|
using pointer = std::shared_ptr<STLedgerEntry>;
|
||||||
using ref = const std::shared_ptr<STLedgerEntry>&;
|
using ref = const std::shared_ptr<STLedgerEntry>&;
|
||||||
|
|
||||||
public:
|
/** Create an empty object with the given key and type. */
|
||||||
|
explicit
|
||||||
|
STLedgerEntry (Keylet const& k);
|
||||||
|
|
||||||
|
STLedgerEntry (LedgerEntryType type,
|
||||||
|
uint256 const& key)
|
||||||
|
: STLedgerEntry(Keylet(type, key))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
STLedgerEntry (const Serializer & s, uint256 const& index);
|
STLedgerEntry (const Serializer & s, uint256 const& index);
|
||||||
|
|
||||||
STLedgerEntry (SerialIter & sit, uint256 const& index);
|
STLedgerEntry (SerialIter & sit, uint256 const& index);
|
||||||
STLedgerEntry (LedgerEntryType type, uint256 const& index);
|
|
||||||
|
|
||||||
STLedgerEntry (const STObject & object, uint256 const& index);
|
STLedgerEntry (const STObject & object, uint256 const& index);
|
||||||
|
|
||||||
STBase*
|
STBase*
|
||||||
@@ -57,69 +68,81 @@ public:
|
|||||||
{
|
{
|
||||||
return STI_LEDGERENTRY;
|
return STI_LEDGERENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getFullText () const override;
|
std::string getFullText () const override;
|
||||||
|
|
||||||
std::string getText () const override;
|
std::string getText () const override;
|
||||||
|
|
||||||
Json::Value getJson (int options) const override;
|
Json::Value getJson (int options) const override;
|
||||||
|
|
||||||
/** Returns the 'key' (or 'index') of this item.
|
/** Returns the 'key' (or 'index') of this item.
|
||||||
The key identifies this entry's position in
|
The key identifies this entry's position in
|
||||||
the SHAMap associative container.
|
the SHAMap associative container.
|
||||||
*/
|
*/
|
||||||
|
uint256 const&
|
||||||
|
key() const
|
||||||
|
{
|
||||||
|
return key_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
uint256 const& getIndex () const
|
uint256 const& getIndex () const
|
||||||
{
|
{
|
||||||
return mIndex;
|
return key_;
|
||||||
}
|
|
||||||
void setIndex (uint256 const& i)
|
|
||||||
{
|
|
||||||
mIndex = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setImmutable ()
|
void setImmutable ()
|
||||||
{
|
{
|
||||||
mMutable = false;
|
mMutable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMutable ()
|
bool isMutable ()
|
||||||
{
|
{
|
||||||
return mMutable;
|
return mMutable;
|
||||||
}
|
}
|
||||||
STLedgerEntry::pointer getMutable () const;
|
|
||||||
|
|
||||||
LedgerEntryType getType () const
|
LedgerEntryType getType () const
|
||||||
{
|
{
|
||||||
return mType;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint16_t getVersion () const
|
std::uint16_t getVersion () const
|
||||||
{
|
{
|
||||||
return getFieldU16 (sfLedgerEntryType);
|
return getFieldU16 (sfLedgerEntryType);
|
||||||
}
|
}
|
||||||
LedgerFormats::Item const* getFormat ()
|
|
||||||
{
|
|
||||||
return mFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isThreadedType() const; // is this a ledger entry that can be threaded
|
bool isThreadedType() const; // is this a ledger entry that can be threaded
|
||||||
|
|
||||||
bool isThreaded () const; // is this ledger entry actually threaded
|
bool isThreaded () const; // is this ledger entry actually threaded
|
||||||
|
|
||||||
bool hasOneOwner () const; // This node has one other node that owns it
|
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)
|
bool hasTwoOwners () const; // This node has two nodes that own it (like ripple balance)
|
||||||
|
|
||||||
RippleAddress getOwner () const;
|
RippleAddress getOwner () const;
|
||||||
|
|
||||||
RippleAddress getFirstOwner () const;
|
RippleAddress getFirstOwner () const;
|
||||||
|
|
||||||
RippleAddress getSecondOwner () const;
|
RippleAddress getSecondOwner () const;
|
||||||
|
|
||||||
uint256 getThreadedTransaction () const;
|
uint256 getThreadedTransaction () const;
|
||||||
|
|
||||||
std::uint32_t getThreadedLedger () const;
|
std::uint32_t getThreadedLedger () const;
|
||||||
|
|
||||||
bool thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256 & prevTxID,
|
bool thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256 & prevTxID,
|
||||||
std::uint32_t & prevLedgerID);
|
std::uint32_t & prevLedgerID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Make STObject comply with the template for this SLE type
|
/* Make STObject comply with the template for this SLE type
|
||||||
Can throw
|
Can throw
|
||||||
*/
|
*/
|
||||||
void setSLEType ();
|
void setSLEType ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mIndex;
|
uint256 key_;
|
||||||
LedgerEntryType mType;
|
LedgerEntryType type_;
|
||||||
LedgerFormats::Item const* mFormat;
|
LedgerFormats::Item const* mFormat;
|
||||||
bool mMutable;
|
bool mMutable;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SLE = STLedgerEntry;
|
using SLE = STLedgerEntry;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <ripple/basics/SHA512Half.h>
|
#include <ripple/basics/SHA512Half.h>
|
||||||
#include <ripple/protocol/Indexes.h>
|
#include <ripple/protocol/Indexes.h>
|
||||||
#include <beast/utility/static_initializer.h>
|
#include <beast/utility/static_initializer.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -192,4 +193,118 @@ getSignerListIndex (Account const& account)
|
|||||||
account);
|
account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace keylet {
|
||||||
|
|
||||||
|
Keylet account_t::operator()(
|
||||||
|
Account const& id) const
|
||||||
|
{
|
||||||
|
return { ltACCOUNT_ROOT,
|
||||||
|
getAccountRootIndex(id) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet account_t::operator()(
|
||||||
|
RippleAddress const& ra) const
|
||||||
|
{
|
||||||
|
return { ltACCOUNT_ROOT,
|
||||||
|
getAccountRootIndex(ra.getAccountID()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet owndir_t::operator()(
|
||||||
|
Account const& id) const
|
||||||
|
{
|
||||||
|
return { ltDIR_NODE,
|
||||||
|
getOwnerDirIndex(id) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet skip_t::operator()() const
|
||||||
|
{
|
||||||
|
return { ltLEDGER_HASHES,
|
||||||
|
getLedgerHashIndex() };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet skip_t::operator()(LedgerIndex ledger) const
|
||||||
|
{
|
||||||
|
return { ltLEDGER_HASHES,
|
||||||
|
getLedgerHashIndex(ledger) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet amendments_t::operator()() const
|
||||||
|
{
|
||||||
|
return { ltAMENDMENTS,
|
||||||
|
getLedgerAmendmentIndex() };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet fee_t::operator()() const
|
||||||
|
{
|
||||||
|
return { ltFEE_SETTINGS,
|
||||||
|
getLedgerFeeIndex() };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet book_t::operator()(Book const& b) const
|
||||||
|
{
|
||||||
|
return { ltDIR_NODE,
|
||||||
|
getBookBase(b) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet offer_t::operator()(Account const& id,
|
||||||
|
std::uint32_t seq) const
|
||||||
|
{
|
||||||
|
return { ltOFFER,
|
||||||
|
getOfferIndex(id, seq) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet item_t::operator()(Keylet const& k,
|
||||||
|
std::uint64_t index,
|
||||||
|
LedgerEntryType type) const
|
||||||
|
{
|
||||||
|
return { type,
|
||||||
|
getDirNodeIndex(k.key, index) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet quality_t::operator()(Keylet const& k,
|
||||||
|
std::uint64_t q) const
|
||||||
|
{
|
||||||
|
assert(k.type == ltDIR_NODE);
|
||||||
|
return { ltDIR_NODE,
|
||||||
|
getQualityIndex(k.key, q) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet next_t::operator()(Keylet const& k) const
|
||||||
|
{
|
||||||
|
assert(k.type == ltDIR_NODE);
|
||||||
|
return { ltDIR_NODE,
|
||||||
|
getQualityNext(k.key) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet ticket_t::operator()(Account const& id,
|
||||||
|
std::uint32_t seq) const
|
||||||
|
{
|
||||||
|
return { ltTICKET,
|
||||||
|
getTicketIndex(id, seq) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet trust_t::operator()(Account const& id0,
|
||||||
|
Account const& id1, Currency const& currency) const
|
||||||
|
{
|
||||||
|
return { ltRIPPLE_STATE,
|
||||||
|
getRippleStateIndex(id0, id1, currency) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet trust_t::operator()(Account const& id,
|
||||||
|
Issue const& issue) const
|
||||||
|
{
|
||||||
|
return { ltRIPPLE_STATE,
|
||||||
|
getRippleStateIndex(id, issue) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Keylet signers_t::operator()(Account const& id) const
|
||||||
|
{
|
||||||
|
return { ltSIGNER_LIST,
|
||||||
|
getSignerListIndex(id) };
|
||||||
|
}
|
||||||
|
|
||||||
|
} // keylet
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -28,9 +28,24 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
STLedgerEntry::STLedgerEntry (Keylet const& k)
|
||||||
|
: STObject(sfLedgerEntry)
|
||||||
|
, key_ (k.key)
|
||||||
|
, type_ (k.type)
|
||||||
|
, mMutable (true)
|
||||||
|
{
|
||||||
|
mFormat =
|
||||||
|
LedgerFormats::getInstance().findByType (type_);
|
||||||
|
if (mFormat == nullptr)
|
||||||
|
throw std::runtime_error ("invalid ledger entry type");
|
||||||
|
set (mFormat->elements);
|
||||||
|
setFieldU16 (sfLedgerEntryType,
|
||||||
|
static_cast <std::uint16_t> (mFormat->getType ()));
|
||||||
|
}
|
||||||
|
|
||||||
STLedgerEntry::STLedgerEntry (
|
STLedgerEntry::STLedgerEntry (
|
||||||
SerialIter& sit, uint256 const& index)
|
SerialIter& sit, uint256 const& index)
|
||||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
: STObject (sfLedgerEntry), key_ (index), mMutable (true)
|
||||||
{
|
{
|
||||||
set (sit);
|
set (sit);
|
||||||
setSLEType ();
|
setSLEType ();
|
||||||
@@ -38,7 +53,7 @@ STLedgerEntry::STLedgerEntry (
|
|||||||
|
|
||||||
STLedgerEntry::STLedgerEntry (
|
STLedgerEntry::STLedgerEntry (
|
||||||
const Serializer& s, uint256 const& index)
|
const Serializer& s, uint256 const& index)
|
||||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
: STObject (sfLedgerEntry), key_ (index), mMutable (true)
|
||||||
{
|
{
|
||||||
SerialIter sit (s.slice());
|
SerialIter sit (s.slice());
|
||||||
set (sit);
|
set (sit);
|
||||||
@@ -47,7 +62,7 @@ STLedgerEntry::STLedgerEntry (
|
|||||||
|
|
||||||
STLedgerEntry::STLedgerEntry (
|
STLedgerEntry::STLedgerEntry (
|
||||||
const STObject & object, uint256 const& index)
|
const STObject & object, uint256 const& index)
|
||||||
: STObject (object), mIndex(index), mMutable (true)
|
: STObject (object), key_(index), mMutable (true)
|
||||||
{
|
{
|
||||||
setSLEType ();
|
setSLEType ();
|
||||||
}
|
}
|
||||||
@@ -60,7 +75,7 @@ void STLedgerEntry::setSLEType ()
|
|||||||
if (mFormat == nullptr)
|
if (mFormat == nullptr)
|
||||||
throw std::runtime_error ("invalid ledger entry type");
|
throw std::runtime_error ("invalid ledger entry type");
|
||||||
|
|
||||||
mType = mFormat->getType ();
|
type_ = mFormat->getType ();
|
||||||
if (!setType (mFormat->elements))
|
if (!setType (mFormat->elements))
|
||||||
{
|
{
|
||||||
WriteLog (lsWARNING, SerializedLedger)
|
WriteLog (lsWARNING, SerializedLedger)
|
||||||
@@ -70,30 +85,10 @@ void STLedgerEntry::setSLEType ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STLedgerEntry::STLedgerEntry (LedgerEntryType type, uint256 const& index) :
|
|
||||||
STObject (sfLedgerEntry), mIndex (index), mType (type), mMutable (true)
|
|
||||||
{
|
|
||||||
mFormat = LedgerFormats::getInstance().findByType (type);
|
|
||||||
|
|
||||||
if (mFormat == nullptr)
|
|
||||||
throw std::runtime_error ("invalid ledger entry type");
|
|
||||||
|
|
||||||
set (mFormat->elements);
|
|
||||||
setFieldU16 (sfLedgerEntryType,
|
|
||||||
static_cast <std::uint16_t> (mFormat->getType ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
STLedgerEntry::pointer STLedgerEntry::getMutable () const
|
|
||||||
{
|
|
||||||
STLedgerEntry::pointer ret = std::make_shared<STLedgerEntry> (std::cref (*this));
|
|
||||||
ret->mMutable = true;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string STLedgerEntry::getFullText () const
|
std::string STLedgerEntry::getFullText () const
|
||||||
{
|
{
|
||||||
std::string ret = "\"";
|
std::string ret = "\"";
|
||||||
ret += to_string (mIndex);
|
ret += to_string (key_);
|
||||||
ret += "\" = { ";
|
ret += "\" = { ";
|
||||||
ret += mFormat->getName ();
|
ret += mFormat->getName ();
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
@@ -105,7 +100,7 @@ std::string STLedgerEntry::getFullText () const
|
|||||||
std::string STLedgerEntry::getText () const
|
std::string STLedgerEntry::getText () const
|
||||||
{
|
{
|
||||||
return str (boost::format ("{ %s, %s }")
|
return str (boost::format ("{ %s, %s }")
|
||||||
% to_string (mIndex)
|
% to_string (key_)
|
||||||
% STObject::getText ());
|
% STObject::getText ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +108,7 @@ Json::Value STLedgerEntry::getJson (int options) const
|
|||||||
{
|
{
|
||||||
Json::Value ret (STObject::getJson (options));
|
Json::Value ret (STObject::getJson (options));
|
||||||
|
|
||||||
ret[jss::index] = to_string (mIndex);
|
ret[jss::index] = to_string (key_);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -130,12 +125,12 @@ bool STLedgerEntry::isThreaded () const
|
|||||||
|
|
||||||
bool STLedgerEntry::hasOneOwner () const
|
bool STLedgerEntry::hasOneOwner () const
|
||||||
{
|
{
|
||||||
return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
|
return (type_ != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STLedgerEntry::hasTwoOwners () const
|
bool STLedgerEntry::hasTwoOwners () const
|
||||||
{
|
{
|
||||||
return mType == ltRIPPLE_STATE;
|
return type_ == ltRIPPLE_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RippleAddress STLedgerEntry::getOwner () const
|
RippleAddress STLedgerEntry::getOwner () const
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ ripplePathFind(RippleLineCache::pointer const& cache,
|
|||||||
<< "Trying with an extra path element";
|
<< "Trying with an extra path element";
|
||||||
|
|
||||||
spsComputed.push_back(fullLiquidityPath);
|
spsComputed.push_back(fullLiquidityPath);
|
||||||
lesSandbox.clear();
|
reconstruct(lesSandbox, lpLedger, tapNONE);
|
||||||
rc = path::RippleCalc::rippleCalculate(
|
rc = path::RippleCalc::rippleCalculate(
|
||||||
lesSandbox,
|
lesSandbox,
|
||||||
saMaxAmount, // --> Amount to send is unlimited
|
saMaxAmount, // --> Amount to send is unlimited
|
||||||
|
|||||||
Reference in New Issue
Block a user