|
|
|
|
@@ -15,7 +15,8 @@
|
|
|
|
|
#include "utils.h"
|
|
|
|
|
#include "Log.h"
|
|
|
|
|
|
|
|
|
|
#define DIR_NODE_MAX 32
|
|
|
|
|
// Small for testing, should likely be 32 or 64.
|
|
|
|
|
#define DIR_NODE_MAX 2
|
|
|
|
|
|
|
|
|
|
bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std::string& strHuman)
|
|
|
|
|
{
|
|
|
|
|
@@ -170,32 +171,26 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
|
|
|
|
if (!sleRoot)
|
|
|
|
|
{
|
|
|
|
|
// No root, make it.
|
|
|
|
|
uNodeDir = 0;
|
|
|
|
|
|
|
|
|
|
sleRoot = entryCreate(ltDIR_NODE, uRootIndex);
|
|
|
|
|
|
|
|
|
|
sleNode = sleRoot;
|
|
|
|
|
uNodeDir = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uNodeDir = sleRoot->getIFieldU64(sfIndexPrevious); // Get index to last directory node.
|
|
|
|
|
|
|
|
|
|
uint64 uNodePrevious = uNodeDir;
|
|
|
|
|
uint256 uNodeIndex; // Index of node.
|
|
|
|
|
|
|
|
|
|
if (uNodeDir)
|
|
|
|
|
{
|
|
|
|
|
// Try adding to non-root.
|
|
|
|
|
uNodeIndex = Ledger::getDirNodeIndex(uRootIndex, uNodeDir);
|
|
|
|
|
lspRoot = lepNONE;
|
|
|
|
|
sleNode = mLedger->getDirNode(lspRoot, uNodeIndex);
|
|
|
|
|
sleNode = mLedger->getDirNode(lspRoot, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
|
|
|
|
|
|
|
|
|
assert(sleNode);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Try adding to root.
|
|
|
|
|
uNodeIndex = uRootIndex;
|
|
|
|
|
// Try adding to root. Didn't have a previous set.
|
|
|
|
|
sleNode = sleRoot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -213,24 +208,33 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Have old last point to new node, if it was not root.
|
|
|
|
|
if (uNodeDir == 1)
|
|
|
|
|
{
|
|
|
|
|
// Previous node is root node.
|
|
|
|
|
|
|
|
|
|
sleRoot->setIFieldU64(sfIndexNext, uNodeDir);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Previous node is not root node.
|
|
|
|
|
|
|
|
|
|
lspRoot = lepNONE;
|
|
|
|
|
SLE::pointer slePrevious = mLedger->getDirNode(lspRoot, Ledger::getDirNodeIndex(uRootIndex, uNodeDir-1));
|
|
|
|
|
|
|
|
|
|
slePrevious->setIFieldU64(sfIndexNext, uNodeDir);
|
|
|
|
|
entryModify(slePrevious);
|
|
|
|
|
|
|
|
|
|
sleNode->setIFieldU64(sfIndexPrevious, uNodeDir-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Have root point to new node.
|
|
|
|
|
sleRoot->setIFieldU64(sfIndexPrevious, uNodeDir);
|
|
|
|
|
entryModify(sleRoot);
|
|
|
|
|
|
|
|
|
|
// Have old last point to new node, if it was not root.
|
|
|
|
|
if (uNodePrevious)
|
|
|
|
|
{
|
|
|
|
|
// Previous node is not root node.
|
|
|
|
|
sleNode->setIFieldU64(sfIndexNext, uNodeDir);
|
|
|
|
|
entryModify(sleNode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the new node.
|
|
|
|
|
sleNode = entryCreate(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
|
|
|
|
svIndexes = STVector256();
|
|
|
|
|
sleNode = entryCreate(ltDIR_NODE, uNodeIndex);
|
|
|
|
|
|
|
|
|
|
if (uNodePrevious)
|
|
|
|
|
sleNode->setIFieldU64(sfIndexPrevious, uNodePrevious);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -245,19 +249,20 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
|
|
|
|
return terSUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --> bKeepRoot: True, if we never completely clean up, after we overflow the root node.
|
|
|
|
|
// --> uNodeDir: Node containing entry.
|
|
|
|
|
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
|
|
|
|
|
// --> uLedgerIndex: Value to add to directory.
|
|
|
|
|
// Ledger must be in a state for this to work.
|
|
|
|
|
TransactionEngineResult TransactionEngine::dirDelete(
|
|
|
|
|
bool bKeepRoot,
|
|
|
|
|
const uint64& uNodeDir,
|
|
|
|
|
const uint256& uRootIndex,
|
|
|
|
|
const uint256& uLedgerIndex)
|
|
|
|
|
{
|
|
|
|
|
uint64 uNodeCur = uNodeDir;
|
|
|
|
|
uint256 uNodeIndex = Ledger::getDirNodeIndex(uRootIndex, uNodeCur);
|
|
|
|
|
LedgerStateParms lspNode = lepNONE;
|
|
|
|
|
SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeIndex);
|
|
|
|
|
SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeCur ? Ledger::getDirNodeIndex(uRootIndex, uNodeCur) : uRootIndex);
|
|
|
|
|
|
|
|
|
|
assert(sleNode);
|
|
|
|
|
|
|
|
|
|
@@ -267,8 +272,7 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
|
|
|
|
|
|
|
|
|
return terBAD_LEDGER;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes);
|
|
|
|
|
std::vector<uint256>& vuiIndexes = svIndexes.peekValue();
|
|
|
|
|
std::vector<uint256>::iterator it;
|
|
|
|
|
@@ -278,82 +282,94 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
|
|
|
|
assert(vuiIndexes.end() != it);
|
|
|
|
|
if (vuiIndexes.end() == it)
|
|
|
|
|
{
|
|
|
|
|
assert(false);
|
|
|
|
|
|
|
|
|
|
Log(lsWARNING) << "dirDelete: node not mentioned";
|
|
|
|
|
|
|
|
|
|
return terBAD_LEDGER;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// Remove the element.
|
|
|
|
|
if (vuiIndexes.size() > 1)
|
|
|
|
|
*it = vuiIndexes[vuiIndexes.size()-1];
|
|
|
|
|
|
|
|
|
|
vuiIndexes.resize(vuiIndexes.size()-1);
|
|
|
|
|
|
|
|
|
|
if (vuiIndexes.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
// Node is not being deleted.
|
|
|
|
|
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
|
|
|
|
entryModify(sleNode);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bool bRootDirty = false;
|
|
|
|
|
SLE::pointer sleRoot;
|
|
|
|
|
|
|
|
|
|
// May be able to delete nodes.
|
|
|
|
|
if (uNodeCur)
|
|
|
|
|
if (vuiIndexes.empty())
|
|
|
|
|
{
|
|
|
|
|
// May be able to delete nodes.
|
|
|
|
|
uint64 uNodePrevious = sleNode->getIFieldU64(sfIndexPrevious);
|
|
|
|
|
uint64 uNodeNext = sleNode->getIFieldU64(sfIndexNext);
|
|
|
|
|
|
|
|
|
|
entryDelete(sleNode);
|
|
|
|
|
|
|
|
|
|
// Fix previous link.
|
|
|
|
|
if (uNodePrevious)
|
|
|
|
|
if (!uNodeCur)
|
|
|
|
|
{
|
|
|
|
|
// Just emptied root node.
|
|
|
|
|
|
|
|
|
|
if (!uNodePrevious)
|
|
|
|
|
{
|
|
|
|
|
// Never overflowed the root node. Delete it.
|
|
|
|
|
entryDelete(sleNode);
|
|
|
|
|
}
|
|
|
|
|
// Root overflowed.
|
|
|
|
|
else if (bKeepRoot)
|
|
|
|
|
{
|
|
|
|
|
// Not allowed to delete root node, if it ever overflowed.
|
|
|
|
|
|
|
|
|
|
nothing();
|
|
|
|
|
}
|
|
|
|
|
else if (uNodePrevious != uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
// Have multiple other nodes. Can't delete root node.
|
|
|
|
|
|
|
|
|
|
nothing();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Have only a root node and a last node.
|
|
|
|
|
LedgerStateParms lspLast = lepNONE;
|
|
|
|
|
SLE::pointer sleLast = mLedger->getDirNode(lspLast, Ledger::getDirNodeIndex(uRootIndex, uNodeNext));
|
|
|
|
|
|
|
|
|
|
assert(sleLast);
|
|
|
|
|
|
|
|
|
|
if (sleLast->getIFieldV256(sfIndexes).peekValue().empty())
|
|
|
|
|
{
|
|
|
|
|
// Both nodes are empty.
|
|
|
|
|
|
|
|
|
|
entryDelete(sleNode); // Delete root.
|
|
|
|
|
entryDelete(sleLast); // Delete last.
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Have an entry, can't delete.
|
|
|
|
|
|
|
|
|
|
nothing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Just emptied a non-root node.
|
|
|
|
|
else if (uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
// Not root and not last node. Can delete node.
|
|
|
|
|
|
|
|
|
|
LedgerStateParms lspPrevious = lepNONE;
|
|
|
|
|
SLE::pointer slePrevious = mLedger->getDirNode(lspPrevious, Ledger::getDirNodeIndex(uRootIndex, uNodePrevious));
|
|
|
|
|
SLE::pointer slePrevious = mLedger->getDirNode(lspPrevious, uNodePrevious ? Ledger::getDirNodeIndex(uRootIndex, uNodePrevious) : uRootIndex);
|
|
|
|
|
|
|
|
|
|
assert(slePrevious);
|
|
|
|
|
|
|
|
|
|
LedgerStateParms lspNext = lepNONE;
|
|
|
|
|
SLE::pointer sleNext = mLedger->getDirNode(lspNext, uNodeNext ? Ledger::getDirNodeIndex(uRootIndex, uNodeNext) : uRootIndex);
|
|
|
|
|
|
|
|
|
|
assert(sleNext);
|
|
|
|
|
|
|
|
|
|
if (!slePrevious)
|
|
|
|
|
{
|
|
|
|
|
Log(lsWARNING) << "dirDelete: previous node is missing";
|
|
|
|
|
|
|
|
|
|
return terBAD_LEDGER;
|
|
|
|
|
}
|
|
|
|
|
else if (uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
slePrevious->setIFieldU64(sfIndexNext, uNodeNext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
slePrevious->makeIFieldAbsent(sfIndexNext);
|
|
|
|
|
}
|
|
|
|
|
entryModify(slePrevious);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Read root.
|
|
|
|
|
bRootDirty = true;
|
|
|
|
|
|
|
|
|
|
sleRoot = mLedger->getDirNode(lspNode, uRootIndex);
|
|
|
|
|
|
|
|
|
|
if (uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
sleRoot->setIFieldU64(sfIndexNext, uNodeNext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sleRoot->makeIFieldAbsent(sfIndexNext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fix next link.
|
|
|
|
|
if (uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
LedgerStateParms lspNext = lepNONE;
|
|
|
|
|
SLE::pointer sleNext = mLedger->getDirNode(lspNext, Ledger::getDirNodeIndex(uRootIndex, uNodeNext));
|
|
|
|
|
|
|
|
|
|
assert(sleNext);
|
|
|
|
|
if (!sleNext)
|
|
|
|
|
@@ -362,69 +378,49 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
|
|
|
|
|
|
|
|
|
return terBAD_LEDGER;
|
|
|
|
|
}
|
|
|
|
|
else if (uNodeNext)
|
|
|
|
|
{
|
|
|
|
|
sleNext->setIFieldU64(sfIndexNext, uNodeNext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sleNext->makeIFieldAbsent(sfIndexNext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fix previous to point to its new next.
|
|
|
|
|
slePrevious->setIFieldU64(sfIndexNext, uNodeNext);
|
|
|
|
|
entryModify(slePrevious);
|
|
|
|
|
|
|
|
|
|
// Fix next to point to its new previous.
|
|
|
|
|
sleNext->setIFieldU64(sfIndexPrevious, uNodePrevious);
|
|
|
|
|
entryModify(sleNext);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
// Last node.
|
|
|
|
|
else if (bKeepRoot || uNodePrevious)
|
|
|
|
|
{
|
|
|
|
|
// Read root.
|
|
|
|
|
bRootDirty = true;
|
|
|
|
|
// Not allowed to delete last node as root was overflowed.
|
|
|
|
|
// Or, have pervious entries preventing complete delete.
|
|
|
|
|
|
|
|
|
|
sleRoot = mLedger->getDirNode(lspNode, uRootIndex);
|
|
|
|
|
|
|
|
|
|
if (uNodePrevious)
|
|
|
|
|
{
|
|
|
|
|
sleRoot->setIFieldU64(sfIndexPrevious, uNodePrevious);
|
|
|
|
|
nothing();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sleRoot->makeIFieldAbsent(sfIndexPrevious);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Last and only node besides the root.
|
|
|
|
|
LedgerStateParms lspRoot = lepNONE;
|
|
|
|
|
SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex);
|
|
|
|
|
|
|
|
|
|
if (bRootDirty)
|
|
|
|
|
assert(sleRoot);
|
|
|
|
|
|
|
|
|
|
if (sleRoot->getIFieldV256(sfIndexes).peekValue().empty())
|
|
|
|
|
{
|
|
|
|
|
// Need to update sleRoot;
|
|
|
|
|
uNodeCur = 0;
|
|
|
|
|
// Both nodes are empty.
|
|
|
|
|
|
|
|
|
|
// If we might be able to delete root, load it.
|
|
|
|
|
if (!uNodePrevious && !uNodeNext)
|
|
|
|
|
vuiIndexes = svIndexes.peekValue();
|
|
|
|
|
}
|
|
|
|
|
entryDelete(sleRoot); // Delete root.
|
|
|
|
|
entryDelete(sleNode); // Delete last.
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bRootDirty = true;
|
|
|
|
|
}
|
|
|
|
|
// Root has an entry, can't delete.
|
|
|
|
|
|
|
|
|
|
if (!uNodeCur)
|
|
|
|
|
{
|
|
|
|
|
// Looking at root node.
|
|
|
|
|
uint64 uRootPrevious = sleNode->getIFieldU64(sfIndexPrevious);
|
|
|
|
|
uint64 uRootNext = sleNode->getIFieldU64(sfIndexNext);
|
|
|
|
|
|
|
|
|
|
if (!uRootPrevious && !uRootNext && vuiIndexes.empty())
|
|
|
|
|
{
|
|
|
|
|
entryDelete(sleRoot);
|
|
|
|
|
}
|
|
|
|
|
else if (bRootDirty)
|
|
|
|
|
{
|
|
|
|
|
entryModify(sleRoot);
|
|
|
|
|
}
|
|
|
|
|
nothing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return terSUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set the authorized public ket for an account. May also set the generator map.
|
|
|
|
|
TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransaction& txn, SLE::pointer sleSrc, bool bMustSetGenerator)
|
|
|
|
|
@@ -498,6 +494,8 @@ bool TransactionEngine::entryExists(SLE::pointer sleEntry)
|
|
|
|
|
|
|
|
|
|
SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint256& uIndex)
|
|
|
|
|
{
|
|
|
|
|
assert(!uIndex.isZero());
|
|
|
|
|
|
|
|
|
|
SLE::pointer sleNew = boost::make_shared<SerializedLedgerEntry>(letType);
|
|
|
|
|
|
|
|
|
|
sleNew->setIndex(uIndex);
|
|
|
|
|
@@ -509,6 +507,7 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2
|
|
|
|
|
|
|
|
|
|
void TransactionEngine::entryDelete(SLE::pointer sleEntry)
|
|
|
|
|
{
|
|
|
|
|
assert(sleEntry);
|
|
|
|
|
entryMap::const_iterator it = mEntries.find(sleEntry);
|
|
|
|
|
|
|
|
|
|
switch (it == mEntries.end() ? taaNONE : it->second)
|
|
|
|
|
@@ -531,6 +530,7 @@ void TransactionEngine::entryDelete(SLE::pointer sleEntry)
|
|
|
|
|
|
|
|
|
|
void TransactionEngine::entryModify(SLE::pointer sleEntry)
|
|
|
|
|
{
|
|
|
|
|
assert(sleEntry);
|
|
|
|
|
entryMap::const_iterator it = mEntries.find(sleEntry);
|
|
|
|
|
|
|
|
|
|
switch (it == mEntries.end() ? taaNONE : it->second)
|
|
|
|
|
@@ -553,6 +553,7 @@ void TransactionEngine::entryModify(SLE::pointer sleEntry)
|
|
|
|
|
|
|
|
|
|
void TransactionEngine::entryUnfunded(SLE::pointer sleEntry)
|
|
|
|
|
{
|
|
|
|
|
assert(sleEntry);
|
|
|
|
|
entryMap::const_iterator it = mEntries.find(sleEntry);
|
|
|
|
|
|
|
|
|
|
switch (it == mEntries.end() ? taaNONE : it->second)
|
|
|
|
|
@@ -1216,7 +1217,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
|
|
|
|
|
// Zero balance and eliminating last limit.
|
|
|
|
|
|
|
|
|
|
bDelIndex = true;
|
|
|
|
|
terResult = dirDelete(uSrcRef, Ledger::getRippleDirIndex(uSrcAccountID), sleRippleState->getIndex());
|
|
|
|
|
terResult = dirDelete(true, uSrcRef, Ledger::getRippleDirIndex(uSrcAccountID), sleRippleState->getIndex());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
@@ -2236,11 +2237,11 @@ TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransac
|
|
|
|
|
uint64 uBookNode = sleOffer->getIFieldU64(sfBookNode);
|
|
|
|
|
uint256 uDirectory = sleOffer->getIFieldH256(sfDirectory);
|
|
|
|
|
|
|
|
|
|
terResult = dirDelete(uOwnerNode, Ledger::getOwnerDirIndex(uSrcAccountID), uLedgerIndex);
|
|
|
|
|
terResult = dirDelete(true, uOwnerNode, Ledger::getOwnerDirIndex(uSrcAccountID), uLedgerIndex);
|
|
|
|
|
|
|
|
|
|
// if (terSUCCESS == terResult)
|
|
|
|
|
// {
|
|
|
|
|
// terResult = dirDelete(uBookNode, uDirectory, uLedgerIndex);
|
|
|
|
|
// terResult = dirDelete(false, uBookNode, uDirectory, uLedgerIndex);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
entryDelete(sleOffer);
|
|
|
|
|
|