From 4b79e7dca80795f334dc775103b5ac07c3919af5 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 05:09:23 -0700 Subject: [PATCH] New canonical transaction order code. Tested and working. CanonicalTXSet acts much like a map, but sorts the transactions in a simple order that makes them take fewer passed. --- src/CanonicalTXSet.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ src/CanonicalTXSet.h | 53 +++++++++++++++++++++++++++++++++++++++++ src/LedgerConsensus.cpp | 16 ++++++------- src/LedgerConsensus.h | 3 ++- 4 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 src/CanonicalTXSet.cpp create mode 100644 src/CanonicalTXSet.h diff --git a/src/CanonicalTXSet.cpp b/src/CanonicalTXSet.cpp new file mode 100644 index 0000000000..93ed79ccd4 --- /dev/null +++ b/src/CanonicalTXSet.cpp @@ -0,0 +1,53 @@ + +#include "CanonicalTXSet.h" + +bool CanonicalTXKey::operator<(const CanonicalTXKey& key) const +{ + if (mAccount < key.mAccount) return true; + if (mAccount > key.mAccount) return false; + if (mSeq < key.mSeq) return true; + if (mSeq > key.mSeq) return false; + return mTXid < key.mTXid; +} + +bool CanonicalTXKey::operator>(const CanonicalTXKey& key) const +{ + if (mAccount > key.mAccount) return true; + if (mAccount < key.mAccount) return false; + if (mSeq > key.mSeq) return true; + if (mSeq < key.mSeq) return false; + return mTXid > key.mTXid; +} + +bool CanonicalTXKey::operator<=(const CanonicalTXKey& key) const +{ + if (mAccount < key.mAccount) return true; + if (mAccount > key.mAccount) return false; + if (mSeq < key.mSeq) return true; + if (mSeq > key.mSeq) return false; + return mTXid <= key.mTXid; +} + +bool CanonicalTXKey::operator>=(const CanonicalTXKey& key)const +{ + if (mAccount > key.mAccount) return true; + if (mAccount < key.mAccount) return false; + if (mSeq > key.mSeq) return true; + if (mSeq < key.mSeq) return false; + return mTXid >= key.mTXid; +} + +void CanonicalTXSet::push_back(SerializedTransaction::pointer txn) +{ + uint256 effectiveAccount = mSetHash; + effectiveAccount ^= txn->getSourceAccount().getAccountID().to256(); + mMap.insert(std::make_pair(CanonicalTXKey(effectiveAccount, txn->getSequence(), txn->getTransactionID()), txn)); +} + +void CanonicalTXSet::eraseInc(iterator& it) +{ + iterator tmp = it++; + mMap.erase(tmp); +} + + diff --git a/src/CanonicalTXSet.h b/src/CanonicalTXSet.h new file mode 100644 index 0000000000..f78c580cd9 --- /dev/null +++ b/src/CanonicalTXSet.h @@ -0,0 +1,53 @@ +#ifndef __CANONICAL_TX_SET_ +#define __CANONICAL_TX_SET_ + +#include + +#include "uint256.h" +#include "SerializedTransaction.h" + +class CanonicalTXKey +{ +protected: + uint256 mAccount, mTXid; + uint32 mSeq; + +public: + CanonicalTXKey(const uint256& account, uint32 seq, const uint256& id) + : mAccount(account), mTXid(id), mSeq(seq) { ; } + + bool operator<(const CanonicalTXKey&) const; + bool operator>(const CanonicalTXKey&) const; + bool operator<=(const CanonicalTXKey&) const; + bool operator>=(const CanonicalTXKey&) const; + + bool operator==(const CanonicalTXKey& k) const { return mTXid == k.mTXid; } + bool operator!=(const CanonicalTXKey& k) const { return mTXid != k.mTXid; } +}; + +class CanonicalTXSet +{ +public: + typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; + +protected: + uint256 mSetHash; + std::map mMap; + +public: + CanonicalTXSet(const uint256& lclHash) : mSetHash(lclHash) { ; } + + void push_back(SerializedTransaction::pointer txn); + void erase(const iterator& it) { mMap.erase(it); } + void eraseInc(iterator& it); + + iterator begin() { return mMap.begin(); } + iterator end() { return mMap.end(); } + const_iterator begin() const { return mMap.begin(); } + const_iterator end() const { return mMap.end(); } + size_t size() const { return mMap.size(); } + bool empty() const { return mMap.empty(); } +}; + +#endif diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 4232c57e24..72190d24a0 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -577,7 +577,7 @@ void LedgerConsensus::Saccept(boost::shared_ptr This, SHAMap::p } void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger, - std::list& failedTransactions) + CanonicalTXSet& failedTransactions) { TransactionEngine engine(ledger); @@ -620,16 +620,17 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led do { successes = 0; - std::list::iterator it = failedTransactions.begin(); + CanonicalTXSet::iterator it = failedTransactions.begin(); while (it != failedTransactions.end()) { try { - TransactionEngineResult result = engine.applyTransaction(**it, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0); + TransactionEngineResult result = + engine.applyTransaction(*it->second, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0); if (result <= 0) { if (result == 0) ++successes; - failedTransactions.erase(it++); + failedTransactions.eraseInc(it); } else { @@ -639,7 +640,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led catch (...) { Log(lsWARNING) << " Throws"; - failedTransactions.erase(it++); + failedTransactions.eraseInc(it); } } } while (successes > 0); @@ -665,7 +666,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) } #endif - std::list failedTransactions; + CanonicalTXSet failedTransactions(set->getHash()); applyTransactions(set, newLCL, failedTransactions); newLCL->setClosed(); newLCL->setAccepted(); @@ -703,8 +704,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) ScopedLock sl = theApp->getMasterLedger().getLock(); - applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), - newOL, failedTransactions); + applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, failedTransactions); theApp->getMasterLedger().pushLedger(newLCL, newOL); mState = lcsACCEPTED; diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 820d65a65c..5595435f5a 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -12,6 +12,7 @@ #include "LedgerAcquire.h" #include "LedgerProposal.h" #include "Peer.h" +#include "CanonicalTXSet.h" class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this { // A transaction set we are trying to acquire @@ -113,7 +114,7 @@ protected: void removePosition(LedgerProposal&, bool ours); void sendHaveTxSet(const uint256& set, bool direct); void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger, - std::list& failedTransactions); + CanonicalTXSet& failedTransactions); // manipulating our own position void takeInitialPosition(Ledger::pointer initialLedger);