diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 58d9966419..c053c90f59 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -110,6 +110,7 @@ + @@ -150,6 +151,7 @@ + diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 168f3736bb..b8c3acee1e 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -267,6 +267,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index ad65ddd9f4..10c3e31b19 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -147,7 +147,7 @@ void LedgerEntrySet::entryModify(SLE::pointer& sle) } } -void LedgerEntrySet::entryDelete(SLE::pointer& sle) +void LedgerEntrySet::entryDelete(SLE::pointer& sle, bool unfunded) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -166,6 +166,13 @@ void LedgerEntrySet::entryDelete(SLE::pointer& sle) it->second.mSeq = mSeq; it->second.mEntry = sle; it->second.mAction = taaDELETE; + if (unfunded) + { + assert(sle->getType() == ltOFFER); // only offers can be unfunded + mSet.deleteUnfunded(sle->getIndex(), + sle->getIValueFieldAmount(sfTakerPays), + sle->getIValueFieldAmount(sfTakerGets)); + } break; case taaCREATE: diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index 885281a01f..14f4a38f49 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -55,7 +55,7 @@ public: LedgerEntryAction hasEntry(const uint256& index) const; void entryCache(SLE::pointer&); // Add this entry to the cache void entryCreate(SLE::pointer&); // This entry will be created - void entryDelete(SLE::pointer&); // This entry will be deleted + void entryDelete(SLE::pointer&, bool unfunded); void entryModify(SLE::pointer&); // This entry will be modified // iterator functions diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 311f004edb..1a5bdd3bf9 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -208,6 +208,12 @@ void STVector256::add(Serializer& s) const s.addVL(mValue.empty() ? NULL : mValue[0].begin(), mValue.size() * (256 / 8)); } +bool STVector256::isEquivalent(const SerializedType& t) const +{ + const STVector256* v = dynamic_cast(&t); + return v && (mValue == v->mValue); +} + // // STAccount // diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index c3ba0f0471..21a3ca8f6b 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -83,7 +83,7 @@ public: virtual void add(Serializer& s) const { return; } virtual bool isEquivalent(const SerializedType& t) const - { assert(getSType() == STI_NOTPRESENT); return t.getSType() == STI_NOTPRESENT; } + { std::cerr << getSType() << std::endl; assert(getSType() == STI_NOTPRESENT); return t.getSType() == STI_NOTPRESENT; } bool operator==(const SerializedType& t) const { return (getSType() == t.getSType()) && isEquivalent(t); } @@ -748,6 +748,7 @@ public: const std::vector& peekValue() const { return mValue; } std::vector& peekValue() { return mValue; } + virtual bool isEquivalent(const SerializedType& t) const; std::vector getValue() const { return mValue; } diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index dd3d3a8c8c..50d70ea75d 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -706,7 +706,10 @@ SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint25 { sleEntry = mLedger->getSLE(uIndex); if (sleEntry) + { mNodes.entryCache(sleEntry); + mOrigNodes.entryCache(sleEntry); // So the metadata code can compare to the original + } } else if(action == taaDELETE) assert(false); @@ -727,9 +730,9 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2 } -void TransactionEngine::entryDelete(SLE::pointer sleEntry) +void TransactionEngine::entryDelete(SLE::pointer sleEntry, bool unfunded) { - mNodes.entryDelete(sleEntry); + mNodes.entryDelete(sleEntry, unfunded); } void TransactionEngine::entryModify(SLE::pointer sleEntry) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 144dc79883..6143468d10 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -214,7 +214,7 @@ protected: SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex); SLE::pointer entryCache(LedgerEntryType letType, const uint256& uIndex); - void entryDelete(SLE::pointer sleEntry); + void entryDelete(SLE::pointer sleEntry, bool unfunded = false); void entryModify(SLE::pointer sleEntry); void entryReset(); diff --git a/src/TransactionMeta.cpp b/src/TransactionMeta.cpp index 7948057856..d1f4840e72 100644 --- a/src/TransactionMeta.cpp +++ b/src/TransactionMeta.cpp @@ -1,5 +1,7 @@ #include "TransactionMeta.h" +#include + #include #include @@ -99,6 +101,12 @@ Json::Value TMNEUnfunded::getJson(int) const return Json::Value("delete_unfunded"); } +void TMNEUnfunded::setBalances(const STAmount& first, const STAmount& second) +{ + firstAmount = first; + secondAmount = second; +} + int TMNEUnfunded::compare(const TransactionMetaNodeEntry&) const { assert(false); // Can't be two deletes for same node @@ -115,25 +123,48 @@ TransactionMetaNode::TransactionMetaNode(const uint256& node, SerializerIterator { type = sit.get8(); if (type == TransactionMetaNodeEntry::TMNChangedBalance) - mEntries.insert(boost::shared_ptr(new TMNEBalance(sit))); + mEntries.push_back(new TMNEBalance(sit)); if (type == TransactionMetaNodeEntry::TMNDeleteUnfunded) - mEntries.insert(boost::shared_ptr(new TMNEUnfunded())); + mEntries.push_back(new TMNEUnfunded()); else if (type != TransactionMetaNodeEntry::TMNEndOfMetadata) throw std::runtime_error("Unparseable metadata"); } while (type != TransactionMetaNodeEntry::TMNEndOfMetadata); } -void TransactionMetaNode::addRaw(Serializer& s) const +void TransactionMetaNode::addRaw(Serializer& s) { s.add256(mNode); s.add256(mPreviousTransaction); s.add32(mPreviousLedger); - for (std::set::const_iterator it = mEntries.begin(), end = mEntries.end(); + mEntries.sort(); + for (boost::ptr_vector::const_iterator it = mEntries.begin(), end = mEntries.end(); it != end; ++it) - (*it)->addRaw(s); + it->addRaw(s); s.add8(TransactionMetaNodeEntry::TMNEndOfMetadata); } +TransactionMetaNodeEntry* TransactionMetaNode::findEntry(int nodeType) +{ + for (boost::ptr_vector::iterator it = mEntries.begin(), end = mEntries.end(); + it != end; ++it) + if (it->getType() == nodeType) + return &*it; + return NULL; +} + +void TransactionMetaNode::addNode(TransactionMetaNodeEntry* node) +{ + mEntries.push_back(node); +} + +void TransactionMetaNode::thread(const uint256& prevTx, uint32 prevLgr) +{ + assert((mPreviousLedger == 0) || (mPreviousLedger == prevLgr)); + assert(mPreviousTransaction.isZero() || (mPreviousTransaction == prevTx)); + mPreviousTransaction = prevTx; + mPreviousLedger = prevLgr; +} + Json::Value TransactionMetaNode::getJson(int v) const { Json::Value ret = Json::objectValue; @@ -142,9 +173,9 @@ Json::Value TransactionMetaNode::getJson(int v) const ret["previous_ledger"] = mPreviousLedger; Json::Value e = Json::arrayValue; - for (std::set::const_iterator it = mEntries.begin(), end = mEntries.end(); + for (boost::ptr_vector::const_iterator it = mEntries.begin(), end = mEntries.end(); it != end; ++it) - e.append((*it)->getJson(v)); + e.append(it->getJson(v)); ret["entries"] = e; return ret; @@ -162,16 +193,16 @@ TransactionMetaSet::TransactionMetaSet(uint32 ledger, const std::vector::const_iterator it = mNodes.begin(), end = mNodes.end(); + for (std::map::iterator it = mNodes.begin(), end = mNodes.end(); it != end; ++it) - it->addRaw(s); + it->second.addRaw(s); s.add256(uint256()); } @@ -183,9 +214,9 @@ Json::Value TransactionMetaSet::getJson(int v) const ret["ledger"] = mLedger; Json::Value e = Json::arrayValue; - for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); + for (std::map::const_iterator it = mNodes.begin(), end = mNodes.end(); it != end; ++it) - e.append(it->getJson(v)); + e.append(it->second.getJson(v)); ret["nodes_affected"] = e; return ret; @@ -193,28 +224,14 @@ Json::Value TransactionMetaSet::getJson(int v) const bool TransactionMetaSet::isNodeAffected(const uint256& node) const { - for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); - it != end; ++it) - if (it->getNode() == node) - return true; - return false; -} - -TransactionMetaNode TransactionMetaSet::getAffectedNode(const uint256& node) -{ - for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); - it != end; ++it) - if (it->getNode() == node) - return *it; - return TransactionMetaNode(uint256()); + return mNodes.find(node) != mNodes.end(); } const TransactionMetaNode& TransactionMetaSet::peekAffectedNode(const uint256& node) const { - for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); - it != end; ++it) - if (it->getNode() == node) - return *it; + std::map::const_iterator it = mNodes.find(node); + if (it != mNodes.end()) + return it->second; throw std::runtime_error("Affected node not found"); } @@ -230,3 +247,28 @@ void TransactionMetaSet::swap(TransactionMetaSet& s) assert((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger)); mNodes.swap(s.mNodes); } + +TransactionMetaNode& TransactionMetaSet::modifyNode(const uint256& node) +{ + std::map::iterator it = mNodes.find(node); + if (it != mNodes.end()) + return it->second; + return mNodes.insert(std::make_pair(node, TransactionMetaNode(node))).first->second; +} + +void TransactionMetaSet::threadNode(const uint256& node, const uint256& prevTx, uint32 prevLgr) +{ + modifyNode(node).thread(prevTx, prevLgr); +} + +bool TransactionMetaSet::deleteUnfunded(const uint256& nodeID, + const STAmount& firstBalance, const STAmount &secondBalance) +{ + TransactionMetaNode& node = modifyNode(nodeID); + TMNEUnfunded* entry = dynamic_cast(node.findEntry(TransactionMetaNodeEntry::TMNDeleteUnfunded)); + if (entry) + entry->setBalances(firstBalance, secondBalance); + else + node.addNode(new TMNEUnfunded(firstBalance, secondBalance)); + return true; +} diff --git a/src/TransactionMeta.h b/src/TransactionMeta.h index a0685a1496..5765034186 100644 --- a/src/TransactionMeta.h +++ b/src/TransactionMeta.h @@ -2,9 +2,9 @@ #define __TRANSACTIONMETA__ #include -#include #include +#include #include "../json/value.h" @@ -35,6 +35,12 @@ public: bool operator<=(const TransactionMetaNodeEntry&) const; bool operator>(const TransactionMetaNodeEntry&) const; bool operator>=(const TransactionMetaNodeEntry&) const; + + std::auto_ptr clone() const + { return std::auto_ptr(clone()); } + +protected: + virtual TransactionMetaNodeEntry* clone(void) = 0; }; class TMNEBalance : public TransactionMetaNodeEntry @@ -67,17 +73,27 @@ public: virtual Json::Value getJson(int) const; virtual int compare(const TransactionMetaNodeEntry&) const; + virtual TransactionMetaNodeEntry* clone(void) { return new TMNEBalance(*this); } }; class TMNEUnfunded : public TransactionMetaNodeEntry { // node was deleted because it was unfunded +protected: + STAmount firstAmount, secondAmount; // Amounts left when declared unfunded public: TMNEUnfunded() : TransactionMetaNodeEntry(TMNDeleteUnfunded) { ; } + TMNEUnfunded(const STAmount& f, const STAmount& s) : + TransactionMetaNodeEntry(TMNDeleteUnfunded), firstAmount(f), secondAmount(s) { ; } + void setBalances(const STAmount& firstBalance, const STAmount& secondBalance); virtual void addRaw(Serializer&) const; virtual Json::Value getJson(int) const; virtual int compare(const TransactionMetaNodeEntry&) const; + virtual TransactionMetaNodeEntry* clone(void) { return new TMNEUnfunded(*this); } }; +inline TransactionMetaNodeEntry* new_clone(const TransactionMetaNodeEntry& s) { return s.clone().release(); } +inline void delete_clone(const TransactionMetaNodeEntry* s) { boost::checked_delete(s); } + class TransactionMetaNode { // a node that has been affected by a transaction public: @@ -87,7 +103,7 @@ protected: uint256 mNode; uint256 mPreviousTransaction; uint32 mPreviousLedger; - std::set mEntries; + boost::ptr_vector mEntries; public: TransactionMetaNode(const uint256 &node) : mNode(node) { ; } @@ -95,24 +111,32 @@ public: const uint256& getNode() const { return mNode; } const uint256& getPreviousTransaction() const { return mPreviousTransaction; } uint32 getPreviousLedger() const { return mPreviousLedger; } - const std::set& peekEntries() const { return mEntries; } + const boost::ptr_vector& peekEntries() const { return mEntries; } + + TransactionMetaNodeEntry* findEntry(int nodeType); + void addNode(TransactionMetaNodeEntry*); bool operator<(const TransactionMetaNode& n) const { return mNode < n.mNode; } bool operator<=(const TransactionMetaNode& n) const { return mNode <= n.mNode; } bool operator>(const TransactionMetaNode& n) const { return mNode > n.mNode; } bool operator>=(const TransactionMetaNode& n) const { return mNode >= n.mNode; } + void thread(const uint256& prevTx, uint32 prevLgr); + TransactionMetaNode(const uint256&node, SerializerIterator&); - void addRaw(Serializer&) const; + void addRaw(Serializer&); Json::Value getJson(int) const; }; + class TransactionMetaSet { protected: uint256 mTransactionID; uint32 mLedger; - std::set mNodes; + std::map mNodes; + + TransactionMetaNode& modifyNode(const uint256&); public: TransactionMetaSet() : mLedger(0) { ; } @@ -124,15 +148,14 @@ public: void swap(TransactionMetaSet&); bool isNodeAffected(const uint256&) const; - TransactionMetaNode getAffectedNode(const uint256&); const TransactionMetaNode& peekAffectedNode(const uint256&) const; Json::Value getJson(int) const; - void addRaw(Serializer&) const; + void addRaw(Serializer&); void threadNode(const uint256& node, const uint256& previousTransaction, uint32 previousLedger); bool signedBy(const uint256& node, const STAmount& fee); - bool deleteUnfunded(const uint256& node); + bool deleteUnfunded(const uint256& node, const STAmount& firstBalance, const STAmount& secondBalance); bool adjustBalance(const uint256& node, unsigned flags, const STAmount &amount); bool adjustBalances(const uint256& node, unsigned flags, const STAmount &firstAmt, const STAmount &secondAmt); };