mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Add support for incrementally updating owner count.
This commit is contained in:
@@ -486,6 +486,35 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result, uint32 index)
|
|||||||
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
|
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TER LedgerEntrySet::dirCount(const uint256& uRootIndex, uint32& uCount)
|
||||||
|
{
|
||||||
|
uint64 uNodeDir = 0;
|
||||||
|
|
||||||
|
uCount = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SLE::pointer sleNode = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
||||||
|
|
||||||
|
if (sleNode)
|
||||||
|
{
|
||||||
|
uCount += sleNode->getFieldV256(sfIndexes).peekValue().size();
|
||||||
|
|
||||||
|
uNodeDir = sleNode->getFieldU64(sfIndexNext); // Get next node.
|
||||||
|
}
|
||||||
|
else if (uNodeDir)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "dirCount: no such node";
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
|
||||||
|
return tefBAD_LEDGER;
|
||||||
|
}
|
||||||
|
} while (uNodeDir);
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// <-- uNodeDir: For deletion, present to make dirDelete efficient.
|
// <-- uNodeDir: For deletion, present to make dirDelete efficient.
|
||||||
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
|
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
|
||||||
// --> uLedgerIndex: Value to add to directory.
|
// --> uLedgerIndex: Value to add to directory.
|
||||||
@@ -814,11 +843,53 @@ bool LedgerEntrySet::dirNext(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is a count, adjust the owner count by iAmount. Otherwise, compute the owner count and store it.
|
||||||
|
TER LedgerEntrySet::ownerCountAdjust(const uint160& uOwnerID, int iAmount, SLE::ref sleAccountRoot)
|
||||||
|
{
|
||||||
|
SLE::pointer sleHold = sleAccountRoot
|
||||||
|
? SLE::pointer()
|
||||||
|
: entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uOwnerID));
|
||||||
|
|
||||||
|
SLE::ref sleRoot = sleAccountRoot
|
||||||
|
? sleAccountRoot
|
||||||
|
: sleHold;
|
||||||
|
|
||||||
|
const bool bHaveOwnerCount = sleRoot->isFieldPresent(sfOwnerCount);
|
||||||
|
TER terResult;
|
||||||
|
|
||||||
|
if (bHaveOwnerCount)
|
||||||
|
{
|
||||||
|
const uint32 uOwnerCount = sleRoot->getFieldU32(sfOwnerCount);
|
||||||
|
|
||||||
|
sleRoot->setFieldU32(sfOwnerCount, uOwnerCount+iAmount);
|
||||||
|
|
||||||
|
terResult = tesSUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 uActualCount;
|
||||||
|
|
||||||
|
terResult = dirCount(Ledger::getOwnerDirIndex(uOwnerID), uActualCount);
|
||||||
|
|
||||||
|
if (tesSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
sleRoot->setFieldU32(sfOwnerCount, uActualCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return terResult;
|
||||||
|
}
|
||||||
|
|
||||||
TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
|
TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
|
||||||
{
|
{
|
||||||
uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode);
|
uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode);
|
||||||
TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
|
TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
|
||||||
|
|
||||||
|
if (tesSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
terResult = ownerCountAdjust(uOwnerID, -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
{
|
{
|
||||||
uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory);
|
uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory);
|
||||||
|
|||||||
@@ -99,8 +99,11 @@ public:
|
|||||||
const uint256& uLedgerIndex, // Item being deleted
|
const uint256& uLedgerIndex, // Item being deleted
|
||||||
const bool bStable);
|
const bool bStable);
|
||||||
|
|
||||||
bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
|
bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
|
||||||
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
|
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
|
||||||
|
TER dirCount(const uint256& uDirIndex, uint32& uCount);
|
||||||
|
|
||||||
|
TER ownerCountAdjust(const uint160& uOwnerID, int iAmount, SLE::ref sleAccountRoot=SLE::pointer());
|
||||||
|
|
||||||
// Offer functions.
|
// Offer functions.
|
||||||
TER offerDelete(const uint256& uOfferIndex);
|
TER offerDelete(const uint256& uOfferIndex);
|
||||||
|
|||||||
@@ -38,4 +38,6 @@ TER OfferCancelTransactor::doApply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -399,6 +399,12 @@ TER OfferCreateTransactor::doApply()
|
|||||||
boost::bind(&Ledger::qualityDirDescriber, _1, saTakerPays.getCurrency(), uPaysIssuerID,
|
boost::bind(&Ledger::qualityDirDescriber, _1, saTakerPays.getCurrency(), uPaysIssuerID,
|
||||||
saTakerGets.getCurrency(), uGetsIssuerID, uRate));
|
saTakerGets.getCurrency(), uGetsIssuerID, uRate));
|
||||||
|
|
||||||
|
// Update owner count.
|
||||||
|
if (tesSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
|
||||||
|
}
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
{
|
{
|
||||||
uint256 uBookBase = Ledger::getBookBase(uPaysCurrency, uPaysIssuerID, uGetsCurrency, uGetsIssuerID);
|
uint256 uBookBase = Ledger::getBookBase(uPaysCurrency, uPaysIssuerID, uGetsCurrency, uGetsIssuerID);
|
||||||
|
|||||||
@@ -9,25 +9,25 @@
|
|||||||
class Transactor
|
class Transactor
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const SerializedTransaction& mTxn;
|
const SerializedTransaction& mTxn;
|
||||||
TransactionEngine* mEngine;
|
TransactionEngine* mEngine;
|
||||||
TransactionEngineParams mParams;
|
TransactionEngineParams mParams;
|
||||||
|
|
||||||
uint160 mTxnAccountID;
|
uint160 mTxnAccountID;
|
||||||
STAmount mFeeDue;
|
STAmount mFeeDue;
|
||||||
STAmount mSourceBalance;
|
STAmount mSourceBalance;
|
||||||
SLE::pointer mTxnAccount;
|
SLE::pointer mTxnAccount;
|
||||||
bool mHasAuthKey;
|
bool mHasAuthKey;
|
||||||
RippleAddress mSigningPubKey;
|
RippleAddress mSigningPubKey;
|
||||||
|
|
||||||
|
|
||||||
TER preCheck();
|
TER preCheck();
|
||||||
TER checkSeq();
|
TER checkSeq();
|
||||||
TER payFee();
|
TER payFee();
|
||||||
|
|
||||||
virtual void calculateFee();
|
virtual void calculateFee();
|
||||||
virtual TER checkSig();
|
virtual TER checkSig();
|
||||||
virtual TER doApply()=0;
|
virtual TER doApply()=0;
|
||||||
|
|
||||||
Transactor(const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine);
|
Transactor(const SerializedTransaction& txn, TransactionEngineParams params, TransactionEngine* engine);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -38,4 +38,6 @@ public:
|
|||||||
TER apply();
|
TER apply();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -53,7 +53,12 @@ TER TrustSetTransactor::doApply()
|
|||||||
if (sleRippleState)
|
if (sleRippleState)
|
||||||
{
|
{
|
||||||
// A line exists in one or more directions.
|
// A line exists in one or more directions.
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
// We might delete a ripple state node if everything is set to defaults.
|
||||||
|
// However, this is problematic as it may make predicting reserve amounts harder for users.
|
||||||
|
// The code here is incomplete.
|
||||||
|
|
||||||
if (!saLimitAmount)
|
if (!saLimitAmount)
|
||||||
{
|
{
|
||||||
// Zeroing line.
|
// Zeroing line.
|
||||||
@@ -135,7 +140,7 @@ TER TrustSetTransactor::doApply()
|
|||||||
if (uQualityOut)
|
if (uQualityOut)
|
||||||
sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
||||||
|
|
||||||
uint64 uSrcRef; // Ignored, dirs never delete.
|
uint64 uSrcRef; // <-- Ignored, dirs never delete.
|
||||||
|
|
||||||
terResult = mEngine->getNodes().dirAdd(
|
terResult = mEngine->getNodes().dirAdd(
|
||||||
uSrcRef,
|
uSrcRef,
|
||||||
@@ -143,12 +148,18 @@ TER TrustSetTransactor::doApply()
|
|||||||
sleRippleState->getIndex(),
|
sleRippleState->getIndex(),
|
||||||
boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID));
|
boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID));
|
||||||
|
|
||||||
|
if (tesSUCCESS == terResult)
|
||||||
|
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
terResult = mEngine->getNodes().dirAdd(
|
terResult = mEngine->getNodes().dirAdd(
|
||||||
uSrcRef,
|
uSrcRef,
|
||||||
Ledger::getOwnerDirIndex(uDstAccountID),
|
Ledger::getOwnerDirIndex(uDstAccountID),
|
||||||
sleRippleState->getIndex(),
|
sleRippleState->getIndex(),
|
||||||
boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID));
|
boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID));
|
||||||
|
|
||||||
|
if (tesSUCCESS == terResult)
|
||||||
|
terResult = mEngine->getNodes().ownerCountAdjust(uDstAccountID, 1, sleDst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(lsINFO) << "doTrustSet<";
|
Log(lsINFO) << "doTrustSet<";
|
||||||
|
|||||||
Reference in New Issue
Block a user