Merge branch 'master' of github.com:jedmccaleb/NewCoin

Conflicts:
	src/LedgerEntrySet.h
This commit is contained in:
Arthur Britto
2012-07-26 12:51:59 -07:00
8 changed files with 182 additions and 106 deletions

106
src/LedgerEntrySet.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include "LedgerEntrySet.h"
#include <boost/make_shared.hpp>
LedgerEntrySet LedgerEntrySet::duplicate()
{
return LedgerEntrySet(mEntries, mSeq + 1);
}
void LedgerEntrySet::setTo(LedgerEntrySet& e)
{
mEntries = e.mEntries;
mSeq = e.mSeq;
}
void LedgerEntrySet::swapWith(LedgerEntrySet& e)
{
std::swap(mSeq, e.mSeq);
mEntries.swap(e.mEntries);
}
SLE::pointer LedgerEntrySet::getEntry(const uint256& index, LedgerEntryAction& action)
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(index);
if (it == mEntries.end())
{
action = taaNONE;
return SLE::pointer();
}
if (it->second.mSeq != mSeq)
{
it->second.mEntry = boost::make_shared<SerializedLedgerEntry>(*it->second.mEntry);
it->second.mSeq = mSeq;
}
action = it->second.mAction;
return it->second.mEntry;
}
LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator it = mEntries.find(index);
if (it == mEntries.end())
return taaNONE;
return it->second.mAction;
}
void LedgerEntrySet::entryCache(SLE::pointer sle)
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaCACHED, mSeq)));
else if (it->second.mAction == taaCACHED)
{
it->second.mSeq = mSeq;
it->second.mEntry = sle;
}
else
throw std::runtime_error("Cache after modify/delete");
}
void LedgerEntrySet::entryCreate(SLE::pointer sle)
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaDELETE, mSeq)));
else if (it->second.mAction == taaDELETE)
throw std::runtime_error("Create after delete"); // We could make this a modify
else if (it->second.mAction == taaMODIFY)
throw std::runtime_error("Create after modify");
else
{
it->second.mSeq = mSeq;
it->second.mEntry = sle;
it->second.mAction = taaDELETE;
}
}
void LedgerEntrySet::entryModify(SLE::pointer sle)
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaMODIFY, mSeq)));
else if (it->second.mAction == taaDELETE)
throw std::runtime_error("Modify after delete");
else
{
it->second.mSeq = mSeq;
it->second.mEntry = sle;
it->second.mAction = (it->second.mAction == taaCREATE) ? taaCREATE : taaDELETE;
}
}
void LedgerEntrySet::entryDelete(SLE::pointer sle)
{
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaDELETE, mSeq)));
else if (it->second.mAction == taaCREATE) // We support delete after create
mEntries.erase(it);
else
{
it->second.mSeq = mSeq;
it->second.mEntry = sle;
it->second.mAction = taaDELETE;
}
}

View File

@@ -1,6 +1,8 @@
#ifndef __LEDGERENTRYSET__
#define __LEDGERENTRYSET__
#include <boost/unordered_map.hpp>
#include "SerializedLedger.h"
enum LedgerEntryAction
@@ -10,7 +12,8 @@ enum LedgerEntryAction
taaMODIFY, // Modifed, must have previously been taaCACHED.
taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY.
taaCREATE, // Newly created.
}
};
class LedgerEntrySetEntry
{
@@ -19,14 +22,18 @@ public:
LedgerEntryAction mAction;
int mSeq;
LedgerEntrySetEntry(SLE::pointer e, LedgerEntryAction a, int s) : mEntry(e), mAction(a), mSeq(s) { ; }
};
class LedgerEntrySet
{
protected:
boost::unordered_map<uint256, LedgerEntrySetEntry> mEntries;
int mSeq;
LedgerEntrySet(const boost::unordered_map<uint256, LedgerEntrySetEntry> &e, int m) : mEntries(e), mSeq(m) { ; }
public:
LedgerEntrySet() : mSeq(0) { ; }
@@ -35,6 +42,10 @@ public:
void setTo(LedgerEntrySet&); // Set this set to have the same contents as another
void swapWith(LedgerEntrySet&); // Swap the contents of two sets
int getSeq() const { return mSeq; }
void bumpSeq() { ++mSeq; }
void clear() { mEntries.empty(); mSeq = 0; }
// basic entry functions
SLE::pointer getEntry(const uint256& index, LedgerEntryAction&);
LedgerEntryAction hasEntry(const uint256& index) const;
@@ -44,11 +55,11 @@ public:
void entryModify(SLE::pointer); // This entry will be modified
// iterator functions
bool isEmpty() const;
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator begin() const;
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator end() const;
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator begin();
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator end();
bool isEmpty() const { return mEntries.empty(); }
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator begin() const { return mEntries.begin(); }
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator end() const { return mEntries.end(); }
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator begin() { return mEntries.begin(); }
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator end() { return mEntries.end(); }
};
#endif

View File

@@ -77,8 +77,6 @@ public:
};
extern std::size_t hash_value(const SHAMapNode& mn);
extern std::size_t hash_value(const uint256& u);
extern std::size_t hash_value(const uint160& u);
class SHAMapItem
{ // an item stored in a SHAMap

View File

@@ -699,26 +699,16 @@ SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint25
if (!uIndex.isZero())
{
entryMap::const_iterator it = mEntries.find(uIndex);
switch (it == mEntries.end() ? taaNONE : it->second.second)
LedgerEntryAction action;
sleEntry = mNodes.getEntry(uIndex, action);
if (!sleEntry)
{
case taaNONE:
sleEntry = mLedger->getSLE(uIndex);
if (sleEntry)
mEntries[uIndex] = std::make_pair(sleEntry, taaCACHED); // Add to cache.
break;
case taaCREATE:
case taaCACHED:
case taaMODIFY:
sleEntry = it->second.first; // Get from cache.
break;
case taaDELETE:
assert(false); // Unexpected case.
break;
sleEntry = mLedger->getSLE(uIndex);
if (sleEntry)
mNodes.entryCache(sleEntry);
}
else if(action == taaDELETE)
assert(false);
}
return sleEntry;
@@ -729,10 +719,8 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2
assert(!uIndex.isZero());
SLE::pointer sleNew = boost::make_shared<SerializedLedgerEntry>(letType);
sleNew->setIndex(uIndex);
mEntries[uIndex] = std::make_pair(sleNew, taaCREATE);
mNodes.entryCreate(sleNew);
return sleNew;
}
@@ -740,60 +728,23 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2
void TransactionEngine::entryDelete(SLE::pointer sleEntry)
{
assert(sleEntry);
const uint256& uIndex = sleEntry->getIndex();
entryMap::const_iterator it = mEntries.find(uIndex);
switch (it == mEntries.end() ? taaNONE : it->second.second)
{
case taaCREATE:
assert(false); // Unexpected case.
break;
case taaCACHED:
case taaMODIFY:
case taaNONE:
mEntries[uIndex] = std::make_pair(sleEntry, taaDELETE); // Upgrade.
break;
case taaDELETE:
nothing(); // No change.
break;
}
mNodes.entryDelete(sleEntry);
}
void TransactionEngine::entryModify(SLE::pointer sleEntry)
{
assert(sleEntry);
const uint256& uIndex = sleEntry->getIndex();
entryMap::const_iterator it = mEntries.find(uIndex);
switch (it == mEntries.end() ? taaNONE : it->second.second)
{
case taaDELETE:
assert(false); // Unexpected case.
break;
case taaCACHED:
case taaNONE:
mEntries[uIndex] = std::make_pair(sleEntry, taaMODIFY); // Upgrade.
break;
case taaCREATE:
case taaMODIFY:
nothing(); // No change.
break;
}
mNodes.entryModify(sleEntry);
}
void TransactionEngine::txnWrite()
{
// Write back the account states and add the transaction to the ledger
BOOST_FOREACH(entryMap_value_type it, mEntries)
for (boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator it = mNodes.begin(), end = mNodes.end();
it != end; ++it)
{
const SLE::pointer& sleEntry = it.second.first;
const SLE::pointer& sleEntry = it->second.mEntry;
switch (it.second.second)
switch (it->second.mAction)
{
case taaNONE:
assert(false);
@@ -824,7 +775,7 @@ void TransactionEngine::txnWrite()
{
Log(lsINFO) << "applyTransaction: taaDELETE: " << sleEntry->getText();
if (!mLedger->peekAccountStateMap()->delItem(it.first))
if (!mLedger->peekAccountStateMap()->delItem(it->first))
assert(false);
}
break;
@@ -834,19 +785,9 @@ void TransactionEngine::txnWrite()
// This is for when a transaction fails from the issuer's point of view and the current changes need to be cleared so other
// actions can be applied to the ledger.
void TransactionEngine::entryReset(const SerializedTransaction& txn)
void TransactionEngine::entryReset()
{
mEntries.clear(); // Lose old SLE modifications.
mTxnAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(mTxnAccountID)); // Get new SLE.
entryModify(mTxnAccount);
STAmount saPaid = txn.getTransactionFee();
STAmount saSrcBalance = mTxnAccount->getIValueFieldAmount(sfBalance);
mTxnAccount->setIFieldAmount(sfBalance, saSrcBalance - saPaid);
// XXX Bump sequence too.
mNodes.setTo(mOrigNodes);
}
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
@@ -855,6 +796,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
Log(lsTRACE) << "applyTransaction>";
assert(mLedger);
mLedgerParentCloseTime = mLedger->getParentCloseTimeNC();
mNodes.clear();
#ifdef DEBUG
if (1)
@@ -1017,7 +959,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
bHaveAuthKey = mTxnAccount->getIFieldPresent(sfAuthorizedKey);
}
// Check if account cliamed.
// Check if account claimed.
if (terSUCCESS == terResult)
{
switch (txn.getTxnType())
@@ -1168,6 +1110,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
if (terSUCCESS == terResult)
{
entryModify(mTxnAccount);
mOrigNodes = mNodes.duplicate();
switch (txn.getTxnType())
{
@@ -1251,7 +1194,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
}
mTxnAccount = SLE::pointer();
mEntries.clear();
mNodes.clear();
mOrigNodes.clear();
mUnfunded.clear();
return terResult;

View File

@@ -7,6 +7,7 @@
#include "Ledger.h"
#include "SerializedTransaction.h"
#include "SerializedLedger.h"
#include "LedgerEntrySet.h"
// A TransactionEngine applies serialized transactions to a ledger
// It can also, verify signatures, verify fees, and give rejection reasons
@@ -97,17 +98,6 @@ enum TransactionEngineParams
tepMETADATA = 5, // put metadata in tree, not transaction
};
enum TransactionAccountAction
{
taaNONE,
taaCACHED, // Unmodified.
taaMODIFY, // Modifed, must have previously been taaCACHED.
taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY.
taaCREATE, // Newly created.
};
typedef std::pair<TransactionAccountAction, SerializedLedgerEntry::pointer> AffectedAccount;
// Hold a path state under incremental application.
class PathState
{
@@ -129,10 +119,7 @@ public:
class TransactionEngine
{
private:
typedef boost::unordered_map<uint256, std::pair<SLE::pointer, TransactionAccountAction> > entryMap;
typedef entryMap::iterator entryMap_iterator;
typedef entryMap::const_iterator entryMap_const_iterator;
typedef entryMap::iterator::value_type entryMap_value_type;
LedgerEntrySet mNodes, mOrigNodes;
TransactionEngineResult dirAdd(
uint64& uNodeDir, // Node of entry.
@@ -194,7 +181,6 @@ protected:
uint160 mTxnAccountID;
SLE::pointer mTxnAccount;
entryMap mEntries;
boost::unordered_set<uint256> mUnfunded; // Indexes that were found unfunded.
SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex);
@@ -202,7 +188,7 @@ protected:
void entryDelete(SLE::pointer sleEntry);
void entryModify(SLE::pointer sleEntry);
void entryReset(const SerializedTransaction& txn);
void entryReset();
STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID);
STAmount rippleTransit(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount);

View File

@@ -89,6 +89,22 @@ Json::Value TMNEBalance::getJson(int p) const
return ret;
}
void TMNEUnfunded::addRaw(Serializer& sit) const
{
sit.add8(mType);
}
Json::Value TMNEUnfunded::getJson(int) const
{
return Json::Value("delete_unfunded");
}
int TMNEUnfunded::compare(const TransactionMetaNodeEntry&) const
{
assert(false); // Can't be two deletes for same node
return 0;
}
TransactionMetaNode::TransactionMetaNode(const uint256& node, SerializerIterator& sit) : mNode(node)
{
mNode = sit.get256();
@@ -100,6 +116,8 @@ TransactionMetaNode::TransactionMetaNode(const uint256& node, SerializerIterator
type = sit.get8();
if (type == TransactionMetaNodeEntry::TMNChangedBalance)
mEntries.insert(boost::shared_ptr<TransactionMetaNodeEntry>(new TMNEBalance(sit)));
if (type == TransactionMetaNodeEntry::TMNDeleteUnfunded)
mEntries.insert(boost::shared_ptr<TransactionMetaNodeEntry>(new TMNEUnfunded()));
else if (type != TransactionMetaNodeEntry::TMNEndOfMetadata)
throw std::runtime_error("Unparseable metadata");
} while (type != TransactionMetaNodeEntry::TMNEndOfMetadata);

View File

@@ -21,6 +21,7 @@ public:
static const int TMNEndOfMetadata = 0;
static const int TMNChangedBalance = 1;
static const int TMNDeleteUnfunded = 2;
int mType;
TransactionMetaNodeEntry(int type) : mType(type) { ; }
@@ -68,6 +69,15 @@ public:
virtual int compare(const TransactionMetaNodeEntry&) const;
};
class TMNEUnfunded : public TransactionMetaNodeEntry
{ // node was deleted because it was unfunded
public:
TMNEUnfunded() : TransactionMetaNodeEntry(TMNDeleteUnfunded) { ; }
virtual void addRaw(Serializer&) const;
virtual Json::Value getJson(int) const;
virtual int compare(const TransactionMetaNodeEntry&) const;
};
class TransactionMetaNode
{ // a node that has been affected by a transaction
public:
@@ -117,10 +127,10 @@ public:
void addRaw(Serializer&) const;
void threadNode(const uint256& node, const uint256& previousTransaction, uint32 previousLedger);
bool signedBy(const uint256& node);
bool signedBy(const uint256& node, const STAmount& fee);
bool deleteUnfunded(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

View File

@@ -469,6 +469,8 @@ inline const uint160 operator^(const uint160& a, const uint160& b) { return (b
inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
extern std::size_t hash_value(const uint160&);
inline const std::string strHex(const uint160& ui)
{
return strHex(ui.begin(), ui.size());
@@ -555,6 +557,7 @@ inline bool operator!=(const uint256& a, const uint256& b) { return (base_ui
inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
extern std::size_t hash_value(const uint256&);
inline int Testuint256AdHoc(std::vector<std::string> vArg)
{