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);
};