diff --git a/src/Amount.cpp b/src/Amount.cpp index 068e1f8e43..a5ba86d145 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -55,7 +55,6 @@ std::string STAmount::getCurrencyHuman() const } else { - uint160 uReserved = mCurrency; Serializer s(160/8); s.add160(mCurrency); @@ -123,7 +122,7 @@ bool STAmount::setValue(const std::string& sAmount, const std::string& sCurrency // ^1 2 0 2 -1 // 123^ 4 3 1 0 // 1^23 4 1 3 -2 - iOffset = -(sAmount.size()-uDecimal-1); + iOffset = -int(sAmount.size()-uDecimal-1); // Issolate integer and fraction. diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp index 6497ede5f6..2a7f38bb7e 100644 --- a/src/ConnectionPool.cpp +++ b/src/ConnectionPool.cpp @@ -463,8 +463,8 @@ bool ConnectionPool::peerScanSet(const std::string& strIp, int iPort) else { // Scan connection terminated, already scheduled for retry. - boost::posix_time::ptime tpNow = boost::posix_time::second_clock::universal_time(); - boost::posix_time::ptime tpNext = ptFromSeconds(db->getInt("ScanNext")); + // boost::posix_time::ptime tpNow = boost::posix_time::second_clock::universal_time(); + // boost::posix_time::ptime tpNext = ptFromSeconds(db->getInt("ScanNext")); //Log(lsINFO) << str(boost::format("Pool: Scan: schedule exists: %s %s (next %s, delay=%d)") // % mScanIp % mScanPort % tpNext % (tpNext-tpNow).total_seconds()); diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 2cdaa0515b..29b87fe378 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -139,7 +139,7 @@ std::string NewcoinAddress::humanNodePublic() const bool NewcoinAddress::setNodePublic(const std::string& strPublic) { - return SetString(strPublic.c_str(), VER_NODE_PUBLIC); + return SetString(strPublic.c_str(), VER_NODE_PUBLIC); } void NewcoinAddress::setNodePublic(const std::vector& vPublic) @@ -302,7 +302,16 @@ std::string NewcoinAddress::humanAccountID() const bool NewcoinAddress::setAccountID(const std::string& strAccountID) { - return SetString(strAccountID.c_str(), VER_ACCOUNT_ID); + if (strAccountID.empty()) + { + setAccountID(uint160()); + + return true; + } + else + { + return SetString(strAccountID.c_str(), VER_ACCOUNT_ID); + } } void NewcoinAddress::setAccountID(const uint160& hash160) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index d91a13e0cd..623dc1d94d 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1504,9 +1504,10 @@ Json::Value RPCServer::doAccountTransactions(const Json::Value& params) else maxLedger = minLedger; - if ((maxLedger < minLedger) || (minLedger < 0) || (maxLedger == 0)) + if ((maxLedger < minLedger) || (maxLedger == 0)) { std::cerr << "minL=" << minLedger << ", maxL=" << maxLedger << std::endl; + return RPCError(rpcLGR_IDXS_INVALID); } diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 0388e3c49d..6df79d7e88 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -65,7 +65,7 @@ public: void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); } void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); } void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); } - void setIFieldU64(SOE_Field field, uint32 v) { return mObject.setValueFieldU64(field, v); } + void setIFieldU64(SOE_Field field, uint64 v) { return mObject.setValueFieldU64(field, v); } void setIFieldH128(SOE_Field field, const uint128& v) { return mObject.setValueFieldH128(field, v); } void setIFieldH160(SOE_Field field, const uint160& v) { return mObject.setValueFieldH160(field, v); } void setIFieldH256(SOE_Field field, const uint256& v) { return mObject.setValueFieldH256(field, v); } diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 436fa8f9ae..b05208d012 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -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. + sleRoot = entryCreate(ltDIR_NODE, uRootIndex); + + sleNode = sleRoot; uNodeDir = 0; - - sleRoot = entryCreate(ltDIR_NODE, uRootIndex); - - sleNode = sleRoot; } 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,163 +272,154 @@ TransactionEngineResult TransactionEngine::dirDelete( return terBAD_LEDGER; } - else + + STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); + std::vector& vuiIndexes = svIndexes.peekValue(); + std::vector::iterator it; + + it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex); + + assert(vuiIndexes.end() != it); + if (vuiIndexes.end() == it) { - STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); - std::vector& vuiIndexes = svIndexes.peekValue(); - std::vector::iterator it; + assert(false); - it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex); + Log(lsWARNING) << "dirDelete: node not mentioned"; - assert(vuiIndexes.end() != it); - if (vuiIndexes.end() == it) + return terBAD_LEDGER; + } + + // Remove the element. + if (vuiIndexes.size() > 1) + *it = vuiIndexes[vuiIndexes.size()-1]; + + vuiIndexes.resize(vuiIndexes.size()-1); + + sleNode->setIFieldV256(sfIndexes, svIndexes); + entryModify(sleNode); + + if (vuiIndexes.empty()) + { + // May be able to delete nodes. + uint64 uNodePrevious = sleNode->getIFieldU64(sfIndexPrevious); + uint64 uNodeNext = sleNode->getIFieldU64(sfIndexNext); + + if (!uNodeCur) { - Log(lsWARNING) << "dirDelete: node not mentioned"; + // Just emptied root node. - 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) + if (!uNodePrevious) { - // Node is not being deleted. - sleNode->setIFieldV256(sfIndexes, svIndexes); - entryModify(sleNode); + // 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 { - bool bRootDirty = false; - SLE::pointer sleRoot; + // Have only a root node and a last node. + LedgerStateParms lspLast = lepNONE; + SLE::pointer sleLast = mLedger->getDirNode(lspLast, Ledger::getDirNodeIndex(uRootIndex, uNodeNext)); - // May be able to delete nodes. - if (uNodeCur) + assert(sleLast); + + if (sleLast->getIFieldV256(sfIndexes).peekValue().empty()) { - uint64 uNodePrevious = sleNode->getIFieldU64(sfIndexPrevious); - uint64 uNodeNext = sleNode->getIFieldU64(sfIndexNext); + // Both nodes are empty. - entryDelete(sleNode); - - // Fix previous link. - if (uNodePrevious) - { - LedgerStateParms lspPrevious = lepNONE; - SLE::pointer slePrevious = mLedger->getDirNode(lspPrevious, Ledger::getDirNodeIndex(uRootIndex, uNodePrevious)); - - assert(slePrevious); - 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) - { - Log(lsWARNING) << "dirDelete: next node is missing"; - - return terBAD_LEDGER; - } - else if (uNodeNext) - { - sleNext->setIFieldU64(sfIndexNext, uNodeNext); - } - else - { - sleNext->makeIFieldAbsent(sfIndexNext); - } - entryModify(sleNext); - } - else - { - // Read root. - bRootDirty = true; - - sleRoot = mLedger->getDirNode(lspNode, uRootIndex); - - if (uNodePrevious) - { - sleRoot->setIFieldU64(sfIndexPrevious, uNodePrevious); - } - else - { - sleRoot->makeIFieldAbsent(sfIndexPrevious); - } - } - - if (bRootDirty) - { - // Need to update sleRoot; - uNodeCur = 0; - - // If we might be able to delete root, load it. - if (!uNodePrevious && !uNodeNext) - vuiIndexes = svIndexes.peekValue(); - } + entryDelete(sleNode); // Delete root. + entryDelete(sleLast); // Delete last. } else { - bRootDirty = true; - } + // Have 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(); } } } + // Just emptied a non-root node. + else if (uNodeNext) + { + // Not root and not last node. Can delete node. - return terSUCCESS; + LedgerStateParms lspPrevious = lepNONE; + 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; + } + + assert(sleNext); + if (!sleNext) + { + Log(lsWARNING) << "dirDelete: next node is missing"; + + return terBAD_LEDGER; + } + + // 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); + } + // Last node. + else if (bKeepRoot || uNodePrevious) + { + // Not allowed to delete last node as root was overflowed. + // Or, have pervious entries preventing complete delete. + + nothing(); + } + else + { + // Last and only node besides the root. + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex); + + assert(sleRoot); + + if (sleRoot->getIFieldV256(sfIndexes).peekValue().empty()) + { + // Both nodes are empty. + + entryDelete(sleRoot); // Delete root. + entryDelete(sleNode); // Delete last. + } + else + { + // Root has an entry, can't delete. + + nothing(); + } + } } + + return terSUCCESS; } // Set the authorized public ket for an account. May also set the generator map. @@ -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(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); diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 498bdcc0ac..99f7444f5c 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -114,6 +114,7 @@ private: const uint256& uLedgerIndex); TransactionEngineResult dirDelete( + bool bKeepRoot, const uint64& uNodeDir, // Node item is mentioned in. const uint256& uRootIndex, const uint256& uLedgerIndex); // Item being deleted