diff --git a/src/TransactionMeta.cpp b/src/TransactionMeta.cpp new file mode 100644 index 0000000000..4c3eee3c3d --- /dev/null +++ b/src/TransactionMeta.cpp @@ -0,0 +1,174 @@ +#include "TransactionMeta.h" + +#include +#include + +bool TransactionMetaNodeEntry::operator<(const TransactionMetaNodeEntry& e) const +{ + if (mType < e.mType) return true; + if (mType > e.mType) return false; + return compare(e) < 0; +} + +bool TransactionMetaNodeEntry::operator<=(const TransactionMetaNodeEntry& e) const +{ + if (mType < e.mType) return true; + if (mType > e.mType) return false; + return compare(e) <= 0; +} + +bool TransactionMetaNodeEntry::operator>(const TransactionMetaNodeEntry& e) const +{ + if (mType > e.mType) return true; + if (mType < e.mType) return false; + return compare(e) > 0; +} + +bool TransactionMetaNodeEntry::operator>=(const TransactionMetaNodeEntry& e) const +{ + if (mType > e.mType) return true; + if (mType < e.mType) return false; + return compare(e) >= 0; +} + +TMNEBalance::TMNEBalance(SerializerIterator& sit) : TransactionMetaNodeEntry(TMNChangedBalance) +{ + mFlags = sit.get32(); + mFirstAmount = * dynamic_cast(STAmount::deserialize(sit, "FirstAmount").get()); + if ((mFlags & TMBTwoAmounts) != 0) + mSecondAmount = * dynamic_cast(STAmount::deserialize(sit, "SecondAmount").get()); +} + +void TMNEBalance::addRaw(Serializer& sit) const +{ + sit.add8(mType); + sit.add32(mFlags); + mFirstAmount.add(sit); + if ((mFlags & TMBTwoAmounts) != 0) + mSecondAmount.add(sit); +} + +void TMNEBalance::adjustFirstAmount(const STAmount& a) +{ + mFirstAmount += a; +} + +void TMNEBalance::adjustSecondAmount(const STAmount& a) +{ + mSecondAmount += a; + mFlags |= TMBTwoAmounts; +} + +int TMNEBalance::compare(const TransactionMetaNodeEntry&) const +{ + assert(false); // should never be two TMNEBalance entries for the same node (as of now) + return 0; +} + +Json::Value TMNEBalance::getJson(int p) const +{ + Json::Value ret(Json::objectValue); + + if ((mFlags & TMBDestroyed) != 0) + ret["destroyed"] = "true"; + if ((mFlags & TMBPaidFee) != 0) + ret["transaction_fee"] = "true"; + + if ((mFlags & TMBRipple) != 0) + ret["type"] = "ripple"; + else if ((mFlags & TMBOffer) != 0) + ret["type"] = "offer"; + else + ret["type"] = "account"; + + if (!mFirstAmount.isZero()) + ret["amount"] = mFirstAmount.getJson(p); + if (!mSecondAmount.isZero()) + ret["second_amount"] = mSecondAmount.getJson(p); + + return ret; +} + +TransactionMetaNode::TransactionMetaNode(const uint256& node, SerializerIterator& sit) : mNode(node) +{ + mNode = sit.get256(); + mPreviousTransaction = sit.get256(); + mPreviousLedger = sit.get32(); + int type; + do + { + type = sit.get8(); + if (type == TransactionMetaNodeEntry::TMNChangedBalance) + mEntries.insert(boost::shared_ptr(new TMNEBalance(sit))); + else if (type != TransactionMetaNodeEntry::TMNEndOfMetadata) + throw std::runtime_error("Unparseable metadata"); + } while (type != TransactionMetaNodeEntry::TMNEndOfMetadata); +} + +void TransactionMetaNode::addRaw(Serializer& s) const +{ + s.add256(mNode); + s.add256(mPreviousTransaction); + s.add32(mPreviousLedger); + for (std::set::const_iterator it = mEntries.begin(), end = mEntries.end(); + it != end; ++it) + (*it)->addRaw(s); + s.add8(TransactionMetaNodeEntry::TMNEndOfMetadata); +} + +Json::Value TransactionMetaNode::getJson(int v) const +{ + Json::Value ret = Json::objectValue; + ret["node"] = mNode.GetHex(); + ret["previous_transaction"] = mPreviousTransaction.GetHex(); + ret["previous_ledger"] = mPreviousLedger; + + Json::Value e = Json::arrayValue; + for (std::set::const_iterator it = mEntries.begin(), end = mEntries.end(); + it != end; ++it) + e.append((*it)->getJson(v)); + ret["entries"] = e; + + return ret; +} + +TransactionMetaSet::TransactionMetaSet(uint32 ledger, const std::vector& vec) : mLedger(ledger) +{ + Serializer s(vec); + SerializerIterator sit(s); + + mTransactionID = sit.get256(); + + do + { + uint256 node = sit.get256(); + if (node.isZero()) + break; + mNodes.insert(TransactionMetaNode(node, sit)); + } while(1); +} + +void TransactionMetaSet::addRaw(Serializer& s) const +{ + s.add256(mTransactionID); + for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); + it != end; ++it) + it->addRaw(s); + s.add256(uint256()); +} + +Json::Value TransactionMetaSet::getJson(int v) const +{ + Json::Value ret = Json::objectValue; + + ret["transaction_id"] = mTransactionID.GetHex(); + ret["ledger"] = mLedger; + + Json::Value e = Json::arrayValue; + for (std::set::const_iterator it = mNodes.begin(), end = mNodes.end(); + it != end; ++it) + e.append(it->getJson(v)); + ret["nodes_affected"] = e; + + return ret; +} diff --git a/src/TransactionMeta.h b/src/TransactionMeta.h new file mode 100644 index 0000000000..4805562e5c --- /dev/null +++ b/src/TransactionMeta.h @@ -0,0 +1,126 @@ +#ifndef __TRANSACTIONMETA__ +#define __TRANSACTIONMETA__ + +#include +#include + +#include + +#include "../json/value.h" + +#include "uint256.h" +#include "Serializer.h" +#include "SerializedTypes.h" + + +class TransactionMetaNodeEntry +{ // a way that a transaction has affected a node +public: + + typedef boost::shared_ptr pointer; + + static const int TMNEndOfMetadata = 0; + static const int TMNChangedBalance = 1; + + int mType; + TransactionMetaNodeEntry(int type) : mType(type) { ; } + + int getType() const { return mType; } + virtual Json::Value getJson(int) const = 0; + virtual void addRaw(Serializer&) const = 0; + virtual int compare(const TransactionMetaNodeEntry&) const = 0; + + bool operator<(const TransactionMetaNodeEntry&) const; + bool operator<=(const TransactionMetaNodeEntry&) const; + bool operator>(const TransactionMetaNodeEntry&) const; + bool operator>=(const TransactionMetaNodeEntry&) const; +}; + +class TMNEBalance : public TransactionMetaNodeEntry +{ // a transaction affected the balance of a node +public: + + static const int TMBTwoAmounts = 0x001; + static const int TMBDestroyed = 0x010; + static const int TMBPaidFee = 0x020; + static const int TMBRipple = 0x100; + static const int TMBOffer = 0x200; + +protected: + unsigned mFlags; + STAmount mFirstAmount, mSecondAmount; + +public: + TMNEBalance() : TransactionMetaNodeEntry(TMNChangedBalance), mFlags(0) { ; } + + TMNEBalance(SerializerIterator&); + virtual void addRaw(Serializer&) const; + + unsigned getFlags() const { return mFlags; } + const STAmount& getFirstAmount() const { return mFirstAmount; } + const STAmount& getSecondAmount() const { return mSecondAmount; } + + void adjustFirstAmount(const STAmount&); + void adjustSecondAmount(const STAmount&); + void setFlags(unsigned flags); + + virtual Json::Value getJson(int) const; + virtual int compare(const TransactionMetaNodeEntry&) const; +}; + +class TransactionMetaNode +{ // a node that has been affected by a transaction +public: + typedef boost::shared_ptr pointer; + +protected: + uint256 mNode; + uint256 mPreviousTransaction; + uint32 mPreviousLedger; + std::set mEntries; + +public: + TransactionMetaNode(const uint256 &node) : mNode(node) { ; } + + const uint256& getNode() const { return mNode; } + const uint256& getPreviousTransaction() const { return mPreviousTransaction; } + uint32 getPreviousLedger() const { return mPreviousLedger; } + const std::set& peekEntries() const { return mEntries; } + + 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; } + + TransactionMetaNode(const uint256&node, SerializerIterator&); + void addRaw(Serializer&) const; + Json::Value getJson(int) const; +}; + +class TransactionMetaSet +{ +protected: + uint256 mTransactionID; + uint32 mLedger; + std::set mNodes; + +public: + TransactionMetaSet(const uint256& txID, uint32 ledger) : mTransactionID(txID), mLedger(ledger) + { ; } + TransactionMetaSet(uint32 ledger, const std::vector&); + + bool isNodeAffected(const uint256&) const; + TransactionMetaNode getAffectedAccount(const uint256&) const; + const TransactionMetaNode& peekAffectedAccount(const uint256&) const; + + Json::Value getJson(int) const; + void addRaw(Serializer&) const; + + void threadNode(const uint256& node, const uint256& previousTransaction, uint32 previousLedger); + bool signedBy(const uint256& node); + bool adjustBalance(const uint256& node, unsigned flags, const STAmount &amount); + bool adjustBalances(const uint256& node, unsigned flags, const STAmount &firstAmt, const STAmount &secondAmt); + +}; + +#endif