mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 10:35:50 +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)
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
|
||||
@@ -984,20 +984,19 @@ Ledger::insert (SLE const& sle)
|
||||
assert(success);
|
||||
}
|
||||
|
||||
boost::optional<SLE>
|
||||
std::shared_ptr<SLE>
|
||||
Ledger::fetch (uint256 const& key,
|
||||
boost::optional<LedgerEntryType> type) const
|
||||
{
|
||||
auto const item =
|
||||
mAccountStateMap->peekItem(key);
|
||||
if (! item)
|
||||
return boost::none;
|
||||
boost::optional<SLE> result;
|
||||
result.emplace(item->peekSerializer(),
|
||||
item->getTag());
|
||||
if (type && result->getType() != type)
|
||||
return {};
|
||||
return result;
|
||||
return nullptr;
|
||||
auto const sle = std::make_shared<SLE>(
|
||||
item->peekSerializer(), item->getTag());
|
||||
if (type && sle->getType() != type)
|
||||
return nullptr;
|
||||
return sle;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1171,7 +1170,8 @@ void Ledger::updateSkipList ()
|
||||
bool created;
|
||||
if (! sle)
|
||||
{
|
||||
sle.emplace(ltLEDGER_HASHES, key);
|
||||
sle = std::make_shared<SLE>(
|
||||
ltLEDGER_HASHES, key);
|
||||
created = true;
|
||||
}
|
||||
else
|
||||
@@ -1198,7 +1198,8 @@ void Ledger::updateSkipList ()
|
||||
bool created;
|
||||
if (! sle)
|
||||
{
|
||||
sle.emplace(ltLEDGER_HASHES, key);
|
||||
sle = std::make_shared<SLE>(
|
||||
ltLEDGER_HASHES, key);
|
||||
created = true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <ripple/app/tx/TransactionMeta.h>
|
||||
#include <ripple/app/ledger/SLECache.h>
|
||||
#include <ripple/app/misc/AccountState.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
@@ -138,10 +139,16 @@ public:
|
||||
then boost::none is returned.
|
||||
@return `empty` if the key is not present
|
||||
*/
|
||||
boost::optional<SLE>
|
||||
std::shared_ptr<SLE>
|
||||
fetch (uint256 const& key, boost::optional<
|
||||
LedgerEntryType> type = boost::none) const;
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
fetch (Keylet const& k) const
|
||||
{
|
||||
return fetch(k.key, k.type);
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// Retrieve immutable ledger entry
|
||||
SLE::pointer getSLEi (uint256 const& uHash) const;
|
||||
|
||||
@@ -34,31 +34,76 @@ namespace ripple {
|
||||
// VFALCO TODO Replace this macro with a documented language constant
|
||||
// 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,
|
||||
std::uint32_t ledgerID, TransactionEngineParams params)
|
||||
LedgerEntrySet::LedgerEntrySet (LedgerEntrySet const& other)
|
||||
: 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);
|
||||
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)
|
||||
@@ -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.
|
||||
// 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);
|
||||
|
||||
@@ -87,7 +132,7 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction&
|
||||
if (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;
|
||||
}
|
||||
|
||||
@@ -95,26 +140,15 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction&
|
||||
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)
|
||||
{
|
||||
assert(key.isNonZero ());
|
||||
assert (mLedger);
|
||||
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 ())
|
||||
{
|
||||
LedgerEntryAction action;
|
||||
Action action;
|
||||
sle = getEntry (key, action);
|
||||
|
||||
if (! sle)
|
||||
@@ -128,10 +162,7 @@ SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const&
|
||||
}
|
||||
else
|
||||
{
|
||||
auto maybe_sle = mLedger->fetch(key, letType);
|
||||
if (maybe_sle)
|
||||
sle = std::make_shared<SLE>(
|
||||
std::move(*maybe_sle));
|
||||
sle = mLedger->fetch(key, letType);
|
||||
}
|
||||
|
||||
if (sle)
|
||||
@@ -160,7 +191,7 @@ void LedgerEntrySet::entryCache (SLE::ref sle)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -185,7 +216,7 @@ void LedgerEntrySet::entryCreate (SLE::ref sle)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -223,7 +254,7 @@ void LedgerEntrySet::entryModify (SLE::ref sle)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -260,7 +291,7 @@ void LedgerEntrySet::entryDelete (SLE::ref sle)
|
||||
if (it == mEntries.end ())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -379,7 +410,8 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -395,15 +427,10 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger,
|
||||
}
|
||||
|
||||
auto sle = ledger->fetch(node);
|
||||
if (sle)
|
||||
{
|
||||
auto p = std::make_shared<SLE>(
|
||||
std::move(*sle));
|
||||
newMods.insert (std::make_pair (node, p));
|
||||
return p;
|
||||
}
|
||||
|
||||
return {};
|
||||
if (! sle)
|
||||
return nullptr;
|
||||
newMods.insert (std::make_pair (node, sle));
|
||||
return sle;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::uint64_t uNodeDir = 0;
|
||||
@@ -679,10 +676,10 @@ TER LedgerEntrySet::dirAdd (
|
||||
if (!sleRoot)
|
||||
{
|
||||
// No root, make it.
|
||||
sleRoot = entryCreate (ltDIR_NODE, uRootIndex);
|
||||
sleRoot = std::make_shared<SLE>(ltDIR_NODE, uRootIndex);
|
||||
sleRoot->setFieldH256 (sfRootIndex, uRootIndex);
|
||||
entryCreate (sleRoot);
|
||||
fDescriber (sleRoot, true);
|
||||
|
||||
sleNode = sleRoot;
|
||||
uNodeDir = 0;
|
||||
}
|
||||
@@ -726,8 +723,10 @@ TER LedgerEntrySet::dirAdd (
|
||||
entryModify (sleRoot);
|
||||
|
||||
// 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);
|
||||
entryCreate (sleNode);
|
||||
|
||||
if (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
|
||||
uint256 ledgerNext = uHash;
|
||||
std::map<uint256, LedgerEntrySetEntry>::const_iterator it;
|
||||
std::map<uint256, Item>::const_iterator it;
|
||||
|
||||
do
|
||||
{
|
||||
@@ -1113,69 +1112,6 @@ uint256 LedgerEntrySet::getNextLedgerIndex (
|
||||
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)
|
||||
{
|
||||
if (!sleOffer)
|
||||
@@ -1197,7 +1133,8 @@ TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer)
|
||||
false, uBookNode, uDirectory, offerIndex, true, false);
|
||||
|
||||
if (tesSUCCESS == terResult)
|
||||
decrementOwnerCount (owner);
|
||||
adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT,
|
||||
getAccountRootIndex(owner)), -1);
|
||||
|
||||
entryDelete (sleOffer);
|
||||
|
||||
@@ -1333,43 +1270,6 @@ bool LedgerEntrySet::isFrozen(
|
||||
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 (
|
||||
const bool bSrcHigh,
|
||||
Account const& uSrcAccountID,
|
||||
@@ -1393,7 +1293,9 @@ TER LedgerEntrySet::trustCreate (
|
||||
auto const& uLowAccountID = !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 uHighNode;
|
||||
@@ -1469,7 +1371,7 @@ TER LedgerEntrySet::trustCreate (
|
||||
}
|
||||
|
||||
sleRippleState->setFieldU32 (sfFlags, uFlags);
|
||||
incrementOwnerCount (sleAccount);
|
||||
adjustOwnerCount(*this, sleAccount, 1);
|
||||
|
||||
// ONLY: Create ripple balance.
|
||||
sleRippleState->setFieldAmount (sfBalance, bSetHigh ? -saBalance : saBalance);
|
||||
@@ -1659,7 +1561,8 @@ TER LedgerEntrySet::rippleCredit (
|
||||
// Sender quality out is 0.
|
||||
{
|
||||
// Clear the reserve of the sender, possibly delete the line!
|
||||
decrementOwnerCount (uSenderID);
|
||||
adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT,
|
||||
getAccountRootIndex(uSenderID)), -1);
|
||||
|
||||
// Clear reserve flag.
|
||||
sleRippleState->setFieldU32 (
|
||||
@@ -1881,9 +1784,9 @@ bool LedgerEntrySet::checkState (
|
||||
{
|
||||
std::uint32_t const flags (state->getFieldU32 (sfFlags));
|
||||
|
||||
auto sender_account = entryCache (ltACCOUNT_ROOT,
|
||||
auto sle = entryCache (ltACCOUNT_ROOT,
|
||||
getAccountRootIndex (sender));
|
||||
assert (sender_account);
|
||||
assert (sle);
|
||||
|
||||
// YYY Could skip this if rippling in reverse.
|
||||
if (before > zero
|
||||
@@ -1893,7 +1796,7 @@ bool LedgerEntrySet::checkState (
|
||||
&& (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
|
||||
// Sender reserve is set.
|
||||
&& static_cast <bool> (flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
|
||||
static_cast <bool> (sender_account->getFlags() & lsfDefaultRipple)
|
||||
static_cast <bool> (sle->getFlags() & lsfDefaultRipple)
|
||||
&& !(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze))
|
||||
&& !state->getFieldAmount (
|
||||
!bSenderHigh ? sfLowLimit : sfHighLimit)
|
||||
@@ -1905,8 +1808,9 @@ bool LedgerEntrySet::checkState (
|
||||
!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
|
||||
// Sender quality out is 0.
|
||||
{
|
||||
// VFALCO Where is the line being deleted?
|
||||
// Clear the reserve of the sender, possibly delete the line!
|
||||
decrementOwnerCount (sender_account);
|
||||
adjustOwnerCount(*this, sle, -1);
|
||||
|
||||
// Clear reserve flag.
|
||||
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
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include <ripple/app/ledger/DeferredCredits.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/protocol/STLedgerEntry.h>
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -50,39 +52,12 @@ enum TransactionEngineParams
|
||||
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
|
||||
{
|
||||
fhIGNORE_FREEZE,
|
||||
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.
|
||||
|
||||
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
|
||||
the modifications. The transaction metadata is built from the LES too.
|
||||
*/
|
||||
/** @{ */
|
||||
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:
|
||||
static char const* getCountedObjectName () { return "LedgerEntrySet"; }
|
||||
LedgerEntrySet& operator= (LedgerEntrySet const&) = delete;
|
||||
|
||||
LedgerEntrySet (
|
||||
Ledger::ref ledger, TransactionEngineParams tep, bool immutable = false)
|
||||
: mLedger (ledger), mParams (tep), mSeq (0), mImmutable (immutable)
|
||||
{
|
||||
}
|
||||
/** Construct a copy.
|
||||
Effects:
|
||||
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 duplicate () const;
|
||||
LedgerEntrySet (Ledger::ref ledger,
|
||||
TransactionEngineParams tep,
|
||||
bool immutable = false);
|
||||
|
||||
/** Apply changes to the backing ledger. */
|
||||
void
|
||||
apply();
|
||||
|
||||
// Swap the contents of two sets
|
||||
void swapWith (LedgerEntrySet&);
|
||||
|
||||
void invalidate ()
|
||||
// VFALCO Only called from RippleCalc.cpp
|
||||
void deprecatedInvalidate()
|
||||
{
|
||||
mLedger.reset ();
|
||||
mDeferredCredits.reset ();
|
||||
@@ -135,26 +153,17 @@ public:
|
||||
++mSeq;
|
||||
}
|
||||
|
||||
void init (Ledger::ref ledger, uint256 const& transactionID,
|
||||
std::uint32_t ledgerID, TransactionEngineParams params);
|
||||
|
||||
void clear ();
|
||||
|
||||
Ledger::pointer& getLedger ()
|
||||
{
|
||||
return mLedger;
|
||||
}
|
||||
|
||||
// basic entry functions
|
||||
SLE::pointer getEntry (uint256 const& index, LedgerEntryAction&);
|
||||
|
||||
void entryCache (SLE::ref); // Add this entry to the cache
|
||||
void entryCreate (SLE::ref); // This entry will be created
|
||||
void entryDelete (SLE::ref); // This entry will be deleted
|
||||
void entryModify (SLE::ref); // This entry will be modified
|
||||
|
||||
// higher-level ledger functions
|
||||
SLE::pointer entryCreate (LedgerEntryType letType, uint256 const& uIndex);
|
||||
SLE::pointer entryCache (LedgerEntryType letType, uint256 const& key);
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
@@ -177,35 +186,24 @@ public:
|
||||
|
||||
bool dirFirst (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||
|
||||
bool dirFirst (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||
|
||||
bool dirNext (uint256 const& uRootIndex, SLE::pointer& sleNode,
|
||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||
|
||||
bool dirNext (uint256 const& uRootIndex, std::shared_ptr<SLE const>& sleNode,
|
||||
unsigned int & uDirEntry, uint256 & uEntryIndex);
|
||||
|
||||
bool dirIsEmpty (uint256 const& uDirIndex);
|
||||
|
||||
TER dirCount (uint256 const& uDirIndex, std::uint32_t & uCount);
|
||||
|
||||
uint256 getNextLedgerIndex (uint256 const& uHash);
|
||||
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.
|
||||
TER offerDelete (SLE::pointer);
|
||||
|
||||
TER offerDelete (uint256 const& offerIndex)
|
||||
{
|
||||
return offerDelete( entryCache (ltOFFER, offerIndex));
|
||||
@@ -220,6 +218,7 @@ public:
|
||||
bool isGlobalFrozen (Account const& issuer);
|
||||
|
||||
void enableDeferredCredits (bool enable=true);
|
||||
|
||||
bool areCreditsDeferred () const;
|
||||
|
||||
TER rippleCredit (
|
||||
@@ -229,8 +228,7 @@ public:
|
||||
STAmount accountHolds (
|
||||
Account const& account, Currency const& currency,
|
||||
Account const& issuer, FreezeHandling freezeHandling);
|
||||
STAmount accountFunds (
|
||||
Account const& account, const STAmount & saDefault, FreezeHandling freezeHandling);
|
||||
|
||||
TER accountSend (
|
||||
Account const& uSenderID, Account const& uReceiverID,
|
||||
const STAmount & saAmount);
|
||||
@@ -248,46 +246,15 @@ public:
|
||||
STAmount const& saSrcLimit,
|
||||
const std::uint32_t uSrcQualityIn = 0,
|
||||
const std::uint32_t uSrcQualityOut = 0);
|
||||
|
||||
TER trustDelete (
|
||||
SLE::ref sleRippleState, Account const& uLowAccountID,
|
||||
Account const& uHighAccountID);
|
||||
|
||||
Json::Value getJson (int) const;
|
||||
|
||||
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)
|
||||
{
|
||||
mSet.setDeliveredAmount (amt);
|
||||
@@ -302,24 +269,7 @@ public:
|
||||
TER transfer_xrp (Account const& from, Account const& to, STAmount const& amount);
|
||||
|
||||
private:
|
||||
Ledger::pointer mLedger;
|
||||
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 getEntry (uint256 const& index, Action&);
|
||||
|
||||
SLE::pointer getForMod (
|
||||
uint256 const& node, Ledger::ref ledger,
|
||||
@@ -359,8 +309,17 @@ private:
|
||||
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;
|
||||
/** @} */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -382,6 +341,30 @@ std::uint32_t
|
||||
rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID,
|
||||
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
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1193,6 +1193,8 @@ bool ApplicationImp::loadOldLedger (
|
||||
|
||||
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);
|
||||
bool ok = loadLedger->addSLE (sle);
|
||||
if (!ok)
|
||||
|
||||
@@ -2496,9 +2496,10 @@ Json::Value NetworkOPsImp::transJson(
|
||||
// If the offer create is not self funded then add the owner balance
|
||||
if (account != amount.issue ().account)
|
||||
{
|
||||
// VFALCO Why are we doing this hack?
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
@@ -2947,8 +2948,13 @@ void NetworkOPsImp::getBookPage (
|
||||
|
||||
m_journal.trace << "getBookPage: bDirectAdvance";
|
||||
|
||||
sleOfferDir = lesActive.entryCache (
|
||||
ltDIR_NODE, lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd));
|
||||
uint256 const ledgerIndex =
|
||||
lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd);
|
||||
if (ledgerIndex.isNonZero())
|
||||
sleOfferDir = lesActive.entryCache (
|
||||
ltDIR_NODE, ledgerIndex);
|
||||
else
|
||||
sleOfferDir.reset();
|
||||
|
||||
if (!sleOfferDir)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <beast/module/core/text/LexicalCast.h>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <tuple>
|
||||
|
||||
namespace ripple {
|
||||
@@ -480,7 +480,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
|
||||
if (valid)
|
||||
{
|
||||
LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE);
|
||||
LedgerEntrySet lesSandbox(
|
||||
cache->getLedger(), tapNONE);
|
||||
auto& sourceAccount = !isXRP (currIssuer.account)
|
||||
? currIssuer.account
|
||||
: isXRP (currIssuer.currency)
|
||||
@@ -505,7 +506,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
m_journal.debug
|
||||
<< iIdentifier << " Trying with an extra path element";
|
||||
spsPaths.push_back (fullLiquidityPath);
|
||||
lesSandbox.clear();
|
||||
reconstruct(lesSandbox, cache->getLedger (), tapNONE);
|
||||
rc = path::RippleCalc::rippleCalculate (
|
||||
lesSandbox,
|
||||
saMaxAmount,
|
||||
|
||||
@@ -268,7 +268,7 @@ TER PathState::pushNode (
|
||||
auto const& backNode = nodes_.back ();
|
||||
if (backNode.isAccount())
|
||||
{
|
||||
auto sleRippleState = lesEntries.entryCache (
|
||||
auto sleRippleState = lesEntries_->entryCache (
|
||||
ltRIPPLE_STATE,
|
||||
getRippleStateIndex (
|
||||
backNode.account_,
|
||||
@@ -295,7 +295,7 @@ TER PathState::pushNode (
|
||||
<< backNode.account_ << " and " << node.account_
|
||||
<< " for " << node.issue_.currency << "." ;
|
||||
|
||||
auto sleBck = lesEntries.entryCache (
|
||||
auto sleBck = lesEntries_->entryCache (
|
||||
ltACCOUNT_ROOT,
|
||||
getAccountRootIndex (backNode.account_));
|
||||
// Is the source account the highest numbered account ID?
|
||||
@@ -323,13 +323,13 @@ TER PathState::pushNode (
|
||||
|
||||
if (resultCode == tesSUCCESS)
|
||||
{
|
||||
STAmount saOwed = creditBalance (lesEntries,
|
||||
STAmount saOwed = creditBalance (*lesEntries_,
|
||||
node.account_, backNode.account_,
|
||||
node.issue_.currency);
|
||||
STAmount saLimit;
|
||||
|
||||
if (saOwed <= zero) {
|
||||
saLimit = creditLimit (lesEntries,
|
||||
saLimit = creditLimit (*lesEntries_,
|
||||
node.account_,
|
||||
backNode.account_,
|
||||
node.issue_.currency);
|
||||
@@ -437,7 +437,7 @@ TER PathState::expandPath (
|
||||
WriteLog (lsTRACE, RippleCalc)
|
||||
<< "expandPath> " << spSourcePath.getJson (0);
|
||||
|
||||
lesEntries = lesSource.duplicate ();
|
||||
lesEntries_.emplace(lesSource);
|
||||
|
||||
terStatus = tesSUCCESS;
|
||||
|
||||
@@ -632,7 +632,7 @@ void PathState::checkFreeze()
|
||||
// Check each order book for a global freeze
|
||||
if (nodes_[i].uFlags & STPathElement::typeIssuer)
|
||||
{
|
||||
sle = lesEntries.entryCache (ltACCOUNT_ROOT,
|
||||
sle = lesEntries_->entryCache (ltACCOUNT_ROOT,
|
||||
getAccountRootIndex (nodes_[i].issue_.account));
|
||||
|
||||
if (sle && sle->isFlag (lsfGlobalFreeze))
|
||||
@@ -651,7 +651,7 @@ void PathState::checkFreeze()
|
||||
|
||||
if (inAccount != outAccount)
|
||||
{
|
||||
sle = lesEntries.entryCache (ltACCOUNT_ROOT,
|
||||
sle = lesEntries_->entryCache (ltACCOUNT_ROOT,
|
||||
getAccountRootIndex (outAccount));
|
||||
|
||||
if (sle && sle->isFlag (lsfGlobalFreeze))
|
||||
@@ -660,7 +660,7 @@ void PathState::checkFreeze()
|
||||
return;
|
||||
}
|
||||
|
||||
sle = lesEntries.entryCache (ltRIPPLE_STATE,
|
||||
sle = lesEntries_->entryCache (ltRIPPLE_STATE,
|
||||
getRippleStateIndex (inAccount,
|
||||
outAccount, currencyID));
|
||||
|
||||
@@ -688,9 +688,9 @@ TER PathState::checkNoRipple (
|
||||
Currency const& currency)
|
||||
{
|
||||
// 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));
|
||||
SLE::pointer sleOut = lesEntries.entryCache (ltRIPPLE_STATE,
|
||||
SLE::pointer sleOut = lesEntries_->entryCache (ltRIPPLE_STATE,
|
||||
getRippleStateIndex (secondAccount, thirdAccount, currency));
|
||||
|
||||
if (!sleIn || !sleOut)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/app/ledger/LedgerEntrySet.h>
|
||||
#include <ripple/app/paths/Node.h>
|
||||
#include <ripple/app/paths/Types.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -102,20 +103,37 @@ class PathState : public CountedObject <PathState>
|
||||
|
||||
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
|
||||
{
|
||||
return !(saInPass && saOutPass);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
TER checkNoRipple (
|
||||
Account const&, Account const&, Account const&, Currency const&);
|
||||
|
||||
/** Clear path structures, and clear each node. */
|
||||
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;
|
||||
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.
|
||||
AccountIssueToNodeIndex umReverse;
|
||||
|
||||
LedgerEntrySet lesEntries;
|
||||
boost::optional<LedgerEntrySet> lesEntries_;
|
||||
|
||||
int mIndex; // Index/rank amoung siblings.
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -288,7 +288,9 @@ TER RippleCalc::rippleCalculate ()
|
||||
assert (mActiveLedger.isValid ());
|
||||
mActiveLedger.swapWith (pathState->ledgerEntries());
|
||||
// For the path, save ledger state.
|
||||
mActiveLedger.invalidate ();
|
||||
|
||||
// VFALCO Can this be done without the function call?
|
||||
mActiveLedger.deprecatedInvalidate();
|
||||
|
||||
iBest = pathState->index ();
|
||||
}
|
||||
@@ -339,7 +341,10 @@ TER RippleCalc::rippleCalculate ()
|
||||
// return.
|
||||
assert (pathState->ledgerEntries().isValid ());
|
||||
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();
|
||||
actualAmountOut_ += pathState->outPass();
|
||||
|
||||
@@ -128,7 +128,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
|
||||
= node().sleOffer->getFieldAmount (sfTakerGets);
|
||||
|
||||
// Funds left.
|
||||
node().saOfferFunds = ledger().accountFunds (
|
||||
node().saOfferFunds = funds (ledger(),
|
||||
node().offerOwnerAccount_,
|
||||
node().saTakerGets,
|
||||
fhZERO_IF_FROZEN);
|
||||
@@ -329,7 +329,7 @@ TER PathCursor::advanceNode (bool const bReverse) const
|
||||
|
||||
// Only the current node is allowed to use the source.
|
||||
|
||||
node().saOfferFunds = ledger().accountFunds (
|
||||
node().saOfferFunds = funds(ledger(),
|
||||
node().offerOwnerAccount_,
|
||||
node().saTakerGets,
|
||||
fhZERO_IF_FROZEN);
|
||||
|
||||
@@ -30,7 +30,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const
|
||||
TER resultCode = tecPATH_DRY;
|
||||
PathCursor pc = *this;
|
||||
|
||||
ledger() = lesCheckpoint.duplicate ();
|
||||
// duplicate
|
||||
reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint);
|
||||
|
||||
for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; )
|
||||
{
|
||||
WriteLog (lsTRACE, RippleCalc)
|
||||
@@ -59,7 +61,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const
|
||||
return resultCode;
|
||||
|
||||
// Do forward.
|
||||
ledger() = lesCheckpoint.duplicate ();
|
||||
// duplicate
|
||||
reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint);
|
||||
|
||||
for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_)
|
||||
{
|
||||
WriteLog (lsTRACE, RippleCalc)
|
||||
|
||||
@@ -55,7 +55,8 @@ public:
|
||||
private:
|
||||
PathCursor(PathCursor const&) = default;
|
||||
|
||||
PathCursor increment(int delta = 1) const {
|
||||
PathCursor increment(int delta = 1) const
|
||||
{
|
||||
return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta};
|
||||
}
|
||||
|
||||
@@ -90,11 +91,6 @@ private:
|
||||
STAmount& saInAct,
|
||||
STAmount& saInFees) const;
|
||||
|
||||
RippleCalc& rippleCalc_;
|
||||
PathState& pathState_;
|
||||
bool multiQuality_;
|
||||
NodeIndex nodeIndex_;
|
||||
|
||||
LedgerEntrySet& ledger() const
|
||||
{
|
||||
return rippleCalc_.mActiveLedger;
|
||||
@@ -129,6 +125,11 @@ private:
|
||||
{
|
||||
return node (restrict (nodeIndex_ + 1));
|
||||
}
|
||||
|
||||
RippleCalc& rippleCalc_;
|
||||
PathState& pathState_;
|
||||
bool multiQuality_;
|
||||
NodeIndex nodeIndex_;
|
||||
};
|
||||
|
||||
} // path
|
||||
|
||||
@@ -46,7 +46,7 @@ class AccountInfo
|
||||
private:
|
||||
Account account_;
|
||||
std::shared_ptr<Ledger> ledger_;
|
||||
boost::optional<SLE const> root_;
|
||||
std::shared_ptr<SLE const> root_;
|
||||
|
||||
public:
|
||||
AccountInfo(Account const& account,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/ledger/LedgerEntrySet.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
@@ -35,11 +36,7 @@ static multisign_t const multisign;
|
||||
// One instance per ledger.
|
||||
// Only one transaction applied at a time.
|
||||
class TransactionEngine
|
||||
: public CountedObject <TransactionEngine>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "TransactionEngine"; }
|
||||
|
||||
private:
|
||||
bool enableMultiSign_ =
|
||||
#if RIPPLE_ENABLE_MULTI_SIGN
|
||||
@@ -48,17 +45,16 @@ private:
|
||||
false;
|
||||
#endif
|
||||
|
||||
LedgerEntrySet mNodes;
|
||||
|
||||
void txnWrite ();
|
||||
boost::optional<LedgerEntrySet> mNodes;
|
||||
|
||||
protected:
|
||||
Ledger::pointer mLedger;
|
||||
int mTxnSeq = 0;
|
||||
|
||||
public:
|
||||
TransactionEngine () = default;
|
||||
TransactionEngine() = default;
|
||||
|
||||
explicit
|
||||
TransactionEngine (Ledger::ref ledger)
|
||||
: mLedger (ledger)
|
||||
{
|
||||
@@ -81,7 +77,7 @@ public:
|
||||
LedgerEntrySet&
|
||||
view ()
|
||||
{
|
||||
return mNodes;
|
||||
return *mNodes;
|
||||
}
|
||||
|
||||
Ledger::ref
|
||||
|
||||
@@ -52,9 +52,11 @@ public:
|
||||
if (!sleTicket)
|
||||
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
|
||||
if (!authorized && sleTicket->isFieldPresent (sfTarget))
|
||||
@@ -77,7 +79,8 @@ public:
|
||||
TER const result = mEngine->view ().dirDelete (false, hint,
|
||||
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);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -122,15 +122,18 @@ private:
|
||||
SLE::pointer amendmentObject (mEngine->view().entryCache (ltAMENDMENTS, index));
|
||||
|
||||
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(),
|
||||
amendment) != amendments.end ())
|
||||
{
|
||||
amendment) != amendments.end ())
|
||||
return tefALREADY;
|
||||
}
|
||||
|
||||
amendments.push_back (amendment);
|
||||
amendmentObject->setFieldV256 (sfAmendments, amendments);
|
||||
@@ -151,7 +154,11 @@ private:
|
||||
SLE::pointer feeObject = mEngine->view().entryCache (ltFEE_SETTINGS, index);
|
||||
|
||||
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
|
||||
// m_journal.trace <<
|
||||
|
||||
@@ -101,11 +101,9 @@ private:
|
||||
{
|
||||
if (offer.fully_consumed ())
|
||||
return true;
|
||||
|
||||
auto const funds (view.accountFunds (offer.owner(),
|
||||
offer.amount().out, fhZERO_IF_FROZEN));
|
||||
|
||||
return (funds <= zero);
|
||||
auto const amount = funds(view, offer.owner(),
|
||||
offer.amount().out, fhZERO_IF_FROZEN);
|
||||
return (amount <= zero);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -202,7 +200,7 @@ private:
|
||||
m_journal.debug << " in: " << offers_direct.tip ().amount().in;
|
||||
m_journal.debug << " out: " << offers_direct.tip ().amount ().out;
|
||||
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 ().amount ().out,
|
||||
fhIGNORE_FREEZE);
|
||||
@@ -222,12 +220,12 @@ private:
|
||||
{
|
||||
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 ().amount ().out,
|
||||
fhIGNORE_FREEZE);
|
||||
|
||||
auto const owner2_funds_before = view.accountFunds (
|
||||
auto const owner2_funds_before = funds(view,
|
||||
offers_leg2.tip ().owner (),
|
||||
offers_leg2.tip ().amount ().out,
|
||||
fhIGNORE_FREEZE);
|
||||
@@ -321,7 +319,7 @@ private:
|
||||
m_journal.debug << " in: " << offer.amount ().in;
|
||||
m_journal.debug << " out: " << offer.amount ().out;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -604,7 +602,7 @@ public:
|
||||
|
||||
result = tecFROZEN;
|
||||
}
|
||||
else if (view.accountFunds (
|
||||
else if (funds(view,
|
||||
mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN) <= zero)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
@@ -795,7 +793,7 @@ public:
|
||||
if (result == tesSUCCESS)
|
||||
{
|
||||
// Update owner count.
|
||||
view.incrementOwnerCount (sleCreator);
|
||||
adjustOwnerCount(view, sleCreator, 1);
|
||||
|
||||
if (m_journal.trace) m_journal.trace <<
|
||||
"adding to book: " << to_string (saTakerPays.issue ()) <<
|
||||
@@ -818,8 +816,7 @@ public:
|
||||
|
||||
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->setFieldU32 (sfSequence, uSequence);
|
||||
sleOffer->setFieldH256 (sfBookDirectory, uDirectory);
|
||||
@@ -827,15 +824,13 @@ public:
|
||||
sleOffer->setFieldAmount (sfTakerGets, saTakerGets);
|
||||
sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode);
|
||||
sleOffer->setFieldU64 (sfBookNode, uBookNode);
|
||||
|
||||
if (uExpiration)
|
||||
sleOffer->setFieldU32 (sfExpiration, uExpiration);
|
||||
|
||||
if (bPassive)
|
||||
sleOffer->setFlag (lsfPassive);
|
||||
|
||||
if (bSell)
|
||||
sleOffer->setFlag (lsfSell);
|
||||
mEngine->view().entryCreate(sleOffer);
|
||||
}
|
||||
|
||||
if (result != tesSUCCESS)
|
||||
|
||||
@@ -85,14 +85,13 @@ public:
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
SLE::pointer sleTicket = mEngine->view().entryCreate (ltTICKET,
|
||||
SLE::pointer sleTicket = std::make_shared<SLE>(ltTICKET,
|
||||
getTicketIndex (mTxnAccountID, mTxn.getSequence ()));
|
||||
|
||||
sleTicket->setFieldAccount (sfAccount, mTxnAccountID);
|
||||
sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ());
|
||||
|
||||
if (expiration != 0)
|
||||
sleTicket->setFieldU32 (sfExpiration, expiration);
|
||||
mEngine->view().entryCreate (sleTicket);
|
||||
|
||||
if (mTxn.isFieldPresent (sfTarget))
|
||||
{
|
||||
@@ -134,7 +133,7 @@ public:
|
||||
sleTicket->setFieldU64(sfOwnerNode, hint);
|
||||
|
||||
// If we succeeded, the new entry counts agains the creator's reserve.
|
||||
mEngine->view ().incrementOwnerCount (mTxnAccount);
|
||||
adjustOwnerCount(mEngine->view(), mTxnAccount, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/tx/LocalTxs.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/CanonicalTXSet.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
|
||||
@@ -125,8 +126,9 @@ public:
|
||||
return true;
|
||||
if (ledger->hasTransaction (txn.getID ()))
|
||||
return true;
|
||||
auto const sle = ledger->fetch(
|
||||
getAccountRootIndex(txn.getAccount()));
|
||||
auto const sle = fetch(*ledger,
|
||||
getAccountRootIndex(txn.getAccount().getAccountID()),
|
||||
getApp().getSLECache());
|
||||
if (! sle)
|
||||
return false;
|
||||
if (sle->getFieldU32 (sfSequence) > txn.getSeq ())
|
||||
|
||||
@@ -122,8 +122,8 @@ OfferStream::step ()
|
||||
// Calculate owner funds
|
||||
// NIKB NOTE The calling code also checks the funds, how expensive is
|
||||
// looking up the funds twice?
|
||||
STAmount const owner_funds (view().accountFunds (
|
||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN));
|
||||
auto const owner_funds = funds(view(),
|
||||
m_offer.owner(), amount.out, fhZERO_IF_FROZEN);
|
||||
|
||||
// Check for unfunded offer
|
||||
if (owner_funds <= zero)
|
||||
@@ -131,7 +131,7 @@ OfferStream::step ()
|
||||
// If the owner's balance in the pristine view is the same,
|
||||
// we haven't modified the balance and therefore the
|
||||
// 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);
|
||||
|
||||
if (original_funds == owner_funds)
|
||||
|
||||
@@ -233,10 +233,11 @@ public:
|
||||
}
|
||||
|
||||
// Create the account.
|
||||
auto const newIndex = getAccountRootIndex (uDstAccountID);
|
||||
sleDst = mEngine->view().entryCreate (ltACCOUNT_ROOT, newIndex);
|
||||
sleDst = std::make_shared<SLE>(ltACCOUNT_ROOT,
|
||||
getAccountRootIndex (uDstAccountID));
|
||||
sleDst->setFieldAccount (sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32 (sfSequence, 1);
|
||||
mEngine->view().entryCreate(sleDst);
|
||||
}
|
||||
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
|
||||
!mTxn.isFieldPresent (sfDestinationTag))
|
||||
|
||||
@@ -234,8 +234,8 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
|
||||
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
|
||||
SLE::pointer signerList (
|
||||
mEngine->view().entryCreate (ltSIGNER_LIST, index));
|
||||
auto signerList = std::make_shared<SLE>(ltSIGNER_LIST, index);
|
||||
mEngine->view().entryCreate (signerList);
|
||||
writeSignersToLedger (signerList);
|
||||
|
||||
// Lambda for call to dirAdd.
|
||||
@@ -259,7 +259,8 @@ SetSignerList::replaceSignerList (uint256 const& index)
|
||||
signerList->setFieldU64 (sfOwnerNode, hint);
|
||||
|
||||
// If we succeeded, the new entry counts against the creator's reserve.
|
||||
mEngine->view ().increaseOwnerCount (mTxnAccount, addedOwnerCount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
mTxnAccount, addedOwnerCount);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -295,13 +296,17 @@ SetSignerList::destroySignerList (uint256 const& index)
|
||||
getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0));
|
||||
|
||||
if (result == tesSUCCESS)
|
||||
mEngine->view ().decreaseOwnerCount (mTxnAccount, removeFromOwnerCount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
mTxnAccount, removeFromOwnerCount);
|
||||
|
||||
mEngine->view ().entryDelete (signerList);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// VFALCO NOTE This name is misleading, the signers
|
||||
// are not written to the ledger they are
|
||||
// added to the SLE.
|
||||
void
|
||||
SetSignerList::writeSignersToLedger (SLE::pointer ledgerEntry)
|
||||
{
|
||||
|
||||
@@ -339,7 +339,8 @@ public:
|
||||
if (bLowReserveSet && !bLowReserved)
|
||||
{
|
||||
// Set reserve for low account.
|
||||
mEngine->view ().incrementOwnerCount (sleLowAccount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
sleLowAccount, 1);
|
||||
uFlagsOut |= lsfLowReserve;
|
||||
|
||||
if (!bHigh)
|
||||
@@ -349,14 +350,16 @@ public:
|
||||
if (bLowReserveClear && bLowReserved)
|
||||
{
|
||||
// Clear reserve for low account.
|
||||
mEngine->view ().decrementOwnerCount (sleLowAccount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
sleLowAccount, -1);
|
||||
uFlagsOut &= ~lsfLowReserve;
|
||||
}
|
||||
|
||||
if (bHighReserveSet && !bHighReserved)
|
||||
{
|
||||
// Set reserve for high account.
|
||||
mEngine->view ().incrementOwnerCount (sleHighAccount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
sleHighAccount, 1);
|
||||
uFlagsOut |= lsfHighReserve;
|
||||
|
||||
if (bHigh)
|
||||
@@ -366,7 +369,8 @@ public:
|
||||
if (bHighReserveClear && bHighReserved)
|
||||
{
|
||||
// Clear reserve for high account.
|
||||
mEngine->view ().decrementOwnerCount (sleHighAccount);
|
||||
adjustOwnerCount(mEngine->view(),
|
||||
sleHighAccount, -1);
|
||||
uFlagsOut &= ~lsfHighReserve;
|
||||
}
|
||||
|
||||
|
||||
@@ -581,9 +581,9 @@ Taker::consume_offer (Offer const& offer, Amounts const& order)
|
||||
}
|
||||
|
||||
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 (
|
||||
|
||||
@@ -31,53 +31,6 @@ namespace ripple {
|
||||
// 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>
|
||||
TransactionEngine::applyTransaction (
|
||||
STTx const& txn,
|
||||
@@ -96,7 +49,8 @@ TransactionEngine::applyTransaction (
|
||||
return std::make_pair(temINVALID_FLAG, false);
|
||||
}
|
||||
|
||||
mNodes.init (mLedger, txID, mLedger->getLedgerSeq (), params);
|
||||
mNodes.emplace(mLedger, txID,
|
||||
mLedger->getLedgerSeq(), params);
|
||||
|
||||
#ifdef BEAST_DEBUG
|
||||
if (1)
|
||||
@@ -146,9 +100,10 @@ TransactionEngine::applyTransaction (
|
||||
// only claim the transaction fee
|
||||
WriteLog (lsDEBUG, TransactionEngine) <<
|
||||
"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 ()));
|
||||
|
||||
if (!txnAcct)
|
||||
@@ -182,7 +137,7 @@ TransactionEngine::applyTransaction (
|
||||
fee = balance;
|
||||
txnAcct->setFieldAmount (sfBalance, balance - fee);
|
||||
txnAcct->setFieldU32 (sfSequence, t_seq + 1);
|
||||
mNodes.entryModify (txnAcct);
|
||||
mNodes->entryModify (txnAcct);
|
||||
didApply = true;
|
||||
}
|
||||
}
|
||||
@@ -202,7 +157,7 @@ TransactionEngine::applyTransaction (
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
transToken (terResult) << ": " << transHuman (terResult);
|
||||
WriteLog (lsFATAL, TransactionEngine) <<
|
||||
mNodes.getJson (0);
|
||||
mNodes->getJson (0);
|
||||
didApply = false;
|
||||
terResult = tefINTERNAL;
|
||||
}
|
||||
@@ -212,9 +167,10 @@ TransactionEngine::applyTransaction (
|
||||
// Transaction succeeded fully or (retries are not allowed and the
|
||||
// transaction could claim a fee)
|
||||
Serializer m;
|
||||
mNodes.calcRawMeta (m, terResult, mTxnSeq++);
|
||||
mNodes->calcRawMeta (m, terResult, mTxnSeq++);
|
||||
|
||||
txnWrite ();
|
||||
assert(mLedger == mNodes->getLedger());
|
||||
mNodes->apply();
|
||||
|
||||
Serializer s;
|
||||
txn.add (s);
|
||||
@@ -253,7 +209,7 @@ TransactionEngine::applyTransaction (
|
||||
}
|
||||
}
|
||||
|
||||
mNodes.clear ();
|
||||
mNodes = boost::none;
|
||||
|
||||
if (!(params & tapOPEN_LEDGER) && isTemMalformed (terResult))
|
||||
{
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
#define RIPPLE_PROTOCOL_INDEXES_H_INCLUDED
|
||||
|
||||
#include <ripple/protocol/LedgerFormats.h>
|
||||
#include <ripple/protocol/Protocol.h>
|
||||
#include <ripple/protocol/RippleAddress.h>
|
||||
#include <ripple/protocol/Serializer.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/protocol/Book.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -89,6 +91,137 @@ getRippleStateIndex (Account const& a, Issue const& issue);
|
||||
|
||||
uint256
|
||||
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
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef 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>
|
||||
|
||||
namespace ripple {
|
||||
@@ -35,10 +35,21 @@ public:
|
||||
using pointer = 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 (SerialIter & sit, uint256 const& index);
|
||||
STLedgerEntry (LedgerEntryType type, uint256 const& index);
|
||||
|
||||
|
||||
STLedgerEntry (const STObject & object, uint256 const& index);
|
||||
|
||||
STBase*
|
||||
@@ -57,69 +68,81 @@ public:
|
||||
{
|
||||
return STI_LEDGERENTRY;
|
||||
}
|
||||
|
||||
std::string getFullText () const override;
|
||||
|
||||
std::string getText () const override;
|
||||
|
||||
Json::Value getJson (int options) const override;
|
||||
|
||||
/** Returns the 'key' (or 'index') of this item.
|
||||
The key identifies this entry's position in
|
||||
the SHAMap associative container.
|
||||
*/
|
||||
uint256 const&
|
||||
key() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
uint256 const& getIndex () const
|
||||
{
|
||||
return mIndex;
|
||||
}
|
||||
void setIndex (uint256 const& i)
|
||||
{
|
||||
mIndex = i;
|
||||
return key_;
|
||||
}
|
||||
|
||||
void setImmutable ()
|
||||
{
|
||||
mMutable = false;
|
||||
}
|
||||
|
||||
bool isMutable ()
|
||||
{
|
||||
return mMutable;
|
||||
}
|
||||
STLedgerEntry::pointer getMutable () const;
|
||||
|
||||
LedgerEntryType getType () const
|
||||
{
|
||||
return mType;
|
||||
return type_;
|
||||
}
|
||||
|
||||
std::uint16_t getVersion () const
|
||||
{
|
||||
return getFieldU16 (sfLedgerEntryType);
|
||||
}
|
||||
LedgerFormats::Item const* getFormat ()
|
||||
{
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
bool isThreadedType() const; // is this a ledger entry that can be threaded
|
||||
|
||||
bool isThreaded () const; // is this ledger entry actually threaded
|
||||
|
||||
bool hasOneOwner () const; // This node has one other node that owns it
|
||||
|
||||
bool hasTwoOwners () const; // This node has two nodes that own it (like ripple balance)
|
||||
|
||||
RippleAddress getOwner () const;
|
||||
|
||||
RippleAddress getFirstOwner () const;
|
||||
|
||||
RippleAddress getSecondOwner () const;
|
||||
|
||||
uint256 getThreadedTransaction () const;
|
||||
|
||||
std::uint32_t getThreadedLedger () const;
|
||||
|
||||
bool thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256 & prevTxID,
|
||||
std::uint32_t & prevLedgerID);
|
||||
|
||||
private:
|
||||
/** Make STObject comply with the template for this SLE type
|
||||
/* Make STObject comply with the template for this SLE type
|
||||
Can throw
|
||||
*/
|
||||
void setSLEType ();
|
||||
|
||||
private:
|
||||
uint256 mIndex;
|
||||
LedgerEntryType mType;
|
||||
uint256 key_;
|
||||
LedgerEntryType type_;
|
||||
LedgerFormats::Item const* mFormat;
|
||||
bool mMutable;
|
||||
bool mMutable;
|
||||
};
|
||||
|
||||
using SLE = STLedgerEntry;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <ripple/basics/SHA512Half.h>
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
#include <beast/utility/static_initializer.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -192,4 +193,118 @@ getSignerListIndex (Account const& 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
|
||||
|
||||
@@ -28,9 +28,24 @@
|
||||
|
||||
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 (
|
||||
SerialIter& sit, uint256 const& index)
|
||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
||||
: STObject (sfLedgerEntry), key_ (index), mMutable (true)
|
||||
{
|
||||
set (sit);
|
||||
setSLEType ();
|
||||
@@ -38,7 +53,7 @@ STLedgerEntry::STLedgerEntry (
|
||||
|
||||
STLedgerEntry::STLedgerEntry (
|
||||
const Serializer& s, uint256 const& index)
|
||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
||||
: STObject (sfLedgerEntry), key_ (index), mMutable (true)
|
||||
{
|
||||
SerialIter sit (s.slice());
|
||||
set (sit);
|
||||
@@ -47,7 +62,7 @@ STLedgerEntry::STLedgerEntry (
|
||||
|
||||
STLedgerEntry::STLedgerEntry (
|
||||
const STObject & object, uint256 const& index)
|
||||
: STObject (object), mIndex(index), mMutable (true)
|
||||
: STObject (object), key_(index), mMutable (true)
|
||||
{
|
||||
setSLEType ();
|
||||
}
|
||||
@@ -60,7 +75,7 @@ void STLedgerEntry::setSLEType ()
|
||||
if (mFormat == nullptr)
|
||||
throw std::runtime_error ("invalid ledger entry type");
|
||||
|
||||
mType = mFormat->getType ();
|
||||
type_ = mFormat->getType ();
|
||||
if (!setType (mFormat->elements))
|
||||
{
|
||||
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 ret = "\"";
|
||||
ret += to_string (mIndex);
|
||||
ret += to_string (key_);
|
||||
ret += "\" = { ";
|
||||
ret += mFormat->getName ();
|
||||
ret += ", ";
|
||||
@@ -105,7 +100,7 @@ std::string STLedgerEntry::getFullText () const
|
||||
std::string STLedgerEntry::getText () const
|
||||
{
|
||||
return str (boost::format ("{ %s, %s }")
|
||||
% to_string (mIndex)
|
||||
% to_string (key_)
|
||||
% STObject::getText ());
|
||||
}
|
||||
|
||||
@@ -113,7 +108,7 @@ Json::Value STLedgerEntry::getJson (int options) const
|
||||
{
|
||||
Json::Value ret (STObject::getJson (options));
|
||||
|
||||
ret[jss::index] = to_string (mIndex);
|
||||
ret[jss::index] = to_string (key_);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -130,12 +125,12 @@ bool STLedgerEntry::isThreaded () const
|
||||
|
||||
bool STLedgerEntry::hasOneOwner () const
|
||||
{
|
||||
return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
|
||||
return (type_ != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
|
||||
}
|
||||
|
||||
bool STLedgerEntry::hasTwoOwners () const
|
||||
{
|
||||
return mType == ltRIPPLE_STATE;
|
||||
return type_ == ltRIPPLE_STATE;
|
||||
}
|
||||
|
||||
RippleAddress STLedgerEntry::getOwner () const
|
||||
|
||||
@@ -306,7 +306,7 @@ ripplePathFind(RippleLineCache::pointer const& cache,
|
||||
<< "Trying with an extra path element";
|
||||
|
||||
spsComputed.push_back(fullLiquidityPath);
|
||||
lesSandbox.clear();
|
||||
reconstruct(lesSandbox, lpLedger, tapNONE);
|
||||
rc = path::RippleCalc::rippleCalculate(
|
||||
lesSandbox,
|
||||
saMaxAmount, // --> Amount to send is unlimited
|
||||
|
||||
Reference in New Issue
Block a user