diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index ac110df3c..06a718b52 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -230,8 +230,70 @@ Json::Value LedgerEntrySet::getJson(int) const return ret; } -void LedgerEntrySet::addRawMeta(Serializer& s, Ledger::pointer origLedger) +SLE::pointer LedgerEntrySet::getForMod(const uint256& node, Ledger::pointer& ledger, + boost::unordered_map& newMods) { + boost::unordered_map::iterator it = mEntries.find(node); + if (it != mEntries.end()) + { + if (it->second.mAction == taaDELETE) + return SLE::pointer(); + if (it->second.mAction == taaCACHED) + it->second.mAction = taaMODIFY; + if (it->second.mSeq != mSeq) + { + it->second.mEntry = boost::make_shared(*it->second.mEntry); + it->second.mSeq = mSeq; + } + return it->second.mEntry; + } + + boost::unordered_map::iterator me = newMods.find(node); + if (me != newMods.end()) + return me->second; + + SLE::pointer ret = ledger->getSLE(node); + if (ret) + newMods.insert(std::make_pair(node, ret)); + return ret; + +} + +bool LedgerEntrySet::threadNode(SLE::pointer& node, const NewcoinAddress& threadTo, Ledger::pointer& ledger, + boost::unordered_map& newMods) +{ + SLE::pointer sle = getForMod(Ledger::getAccountRootIndex(threadTo.getAccountID()), ledger, newMods); + if ((!sle) || (sle->getIndex() == node->getIndex())) // do not self-thread + return false; + return threadNode(node, sle, ledger, newMods); +} + +bool LedgerEntrySet::threadNode(SLE::pointer& node, SLE::pointer& threadTo, Ledger::pointer& ledger, + boost::unordered_map& newMods) +{ + // WRITEME + return false; +} + +bool LedgerEntrySet::threadOwners(SLE::pointer& node, Ledger::pointer& ledger, + boost::unordered_map& newMods) +{ // thread new or modified node to owner or owners + if (node->hasOneOwner()) // thread to owner's account + return threadNode(node, node->getOwner(), ledger, newMods); + else if (node->hasTwoOwners()) // thread to owner's accounts + return + threadNode(node, node->getFirstOwner(), ledger, newMods) || + threadNode(node, node->getSecondOwner(), ledger, newMods); + else + return false; +} + +void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::pointer& origLedger) +{ // calculate the raw meta data and return it. This must be called before the set is committed + + // Entries modified only as a result of building the transaction metadata + boost::unordered_map newMod; + for (boost::unordered_map::const_iterator it = mEntries.begin(), end = mEntries.end(); it != end; ++it) { @@ -257,10 +319,38 @@ void LedgerEntrySet::addRawMeta(Serializer& s, Ledger::pointer origLedger) SLE::pointer origNode = origLedger->getSLE(it->first); SLE::pointer curNode = it->second.mEntry; - // FINISH + if (nType == TMNDeletedNode) + { + threadOwners(origNode, origLedger, newMod); + if (origNode->getType() == ltOFFER) + { // check for non-zero balances + // WRITEME + } + } + + if ((nType == TMNCreatedNode) || (nType == TMNModifiedNode)) + { + if (nType == TMNCreatedNode) // if created, thread to owner(s) + threadOwners(curNode, origLedger, newMod); + + if (curNode->isThreadedType()) // always thread to self + threadNode(curNode, curNode, origLedger, newMod); + + if (nType == TMNModifiedNode) + { + // analyze changes WRITEME + } + + } } } + + // add any new modified nodes to the modification set + for (boost::unordered_map::iterator it = newMod.begin(), end = newMod.end(); + it != end; ++it) + entryCache(it->second); + mSet.addRaw(s); } diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index cf4ee9b28..6d77b3592 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -38,6 +38,18 @@ protected: LedgerEntrySet(const boost::unordered_map &e, const TransactionMetaSet& s, int m) : mEntries(e), mSet(s), mSeq(m) { ; } + SLE::pointer getForMod(const uint256& node, Ledger::pointer& ledger, + boost::unordered_map& newMods); + + bool threadNode(SLE::pointer& node, const NewcoinAddress& threadTo, Ledger::pointer& ledger, + boost::unordered_map& newMods); + + bool threadNode(SLE::pointer& node, SLE::pointer& threadTo, Ledger::pointer& ledger, + boost::unordered_map& newMods); + + bool threadOwners(SLE::pointer& node, Ledger::pointer& ledger, + boost::unordered_map& newMods); + public: LedgerEntrySet() : mSeq(0) { ; } @@ -60,7 +72,7 @@ public: void entryModify(const SLE::pointer&); // This entry will be modified Json::Value getJson(int) const; - void addRawMeta(Serializer&, Ledger::pointer originalLedger); + void calcRawMeta(Serializer&, Ledger::pointer& originalLedger); // iterator functions bool isEmpty() const { return mEntries.empty(); } diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index e79b19c1b..579695236 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -109,6 +109,31 @@ bool SerializedLedgerEntry::thread(const uint256& txID, uint32 ledgerSeq, uint25 return true; } +bool SerializedLedgerEntry::hasOneOwner() +{ + return (mType != ltACCOUNT_ROOT) && (getIFieldIndex(sfAccount) != -1); +} + +bool SerializedLedgerEntry::hasTwoOwners() +{ + return mType == ltRIPPLE_STATE; +} + +NewcoinAddress SerializedLedgerEntry::getOwner() +{ + return getIValueFieldAccount(sfAccount); +} + +NewcoinAddress SerializedLedgerEntry::getFirstOwner() +{ + return getIValueFieldAccount(sfLowID); +} + +NewcoinAddress SerializedLedgerEntry::getSecondOwner() +{ + return getIValueFieldAccount(sfHighID); +} + std::vector SerializedLedgerEntry::getOwners() { std::vector owners; diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 5f66a765d..21faba8c3 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -65,6 +65,11 @@ public: bool isThreadedType(); // is this a ledger entry that can be threaded bool isThreaded(); // is this ledger entry actually threaded + bool hasOneOwner(); // This node has one other node that owns it (like nickname) + bool hasTwoOwners(); // This node has two nodes that own it (like ripple balance) + NewcoinAddress getOwner(); + NewcoinAddress getFirstOwner(); + NewcoinAddress getSecondOwner(); uint256 getThreadedTransaction(); uint32 getThreadedLedger(); bool thread(const uint256& txID, uint32 ledgerSeq, uint256& prevTxID, uint32& prevLedgerID); diff --git a/src/TransactionMeta.cpp b/src/TransactionMeta.cpp index b193afb48..d6c80d9ad 100644 --- a/src/TransactionMeta.cpp +++ b/src/TransactionMeta.cpp @@ -307,4 +307,4 @@ void TransactionMetaSet::deleteUnfunded(const uint256& nodeID, else node.addNode(new TMNEUnfunded(firstBalance, secondBalance)); } -#endif \ No newline at end of file +#endif