diff --git a/js/amount.js b/js/amount.js
index a9e6e839d..10c9ffb39 100644
--- a/js/amount.js
+++ b/js/amount.js
@@ -136,8 +136,8 @@ UInt160.json_rewrite = function (j) {
// Return a new UInt160 from j.
UInt160.from_json = function (j) {
return 'string' === typeof j
- ? (new UInt160()).parse_json(j)
- : j.clone();
+ ? (new UInt160()).parse_json(j)
+ : j.clone();
};
UInt160.prototype.clone = function() {
@@ -232,8 +232,15 @@ var Currency = function () {
this.value = NaN;
}
+// Given "USD" return the json.
+Currency.json_rewrite = function(j) {
+ return Currency.from_json(j).to_json();
+};
+
Currency.from_json = function (j) {
- return (new Currency()).parse_json(j);
+ return 'string' === typeof j
+ ? (new Currency()).parse_json(j)
+ : j.clone();
};
Currency.prototype.clone = function() {
diff --git a/js/remote.js b/js/remote.js
index 8313088f0..9e0b4fedf 100644
--- a/js/remote.js
+++ b/js/remote.js
@@ -914,6 +914,17 @@ Transaction.prototype.submit = function () {
var self = this;
var transaction = this.transaction;
+ if ('string' !== typeof transaction.Account)
+ {
+ this.emit('error', {
+ 'error' : 'invalidAccount',
+ 'error_message' : 'Bad account.'
+ });
+ return;
+ }
+
+ // YYY Might check paths for invalid accounts.
+
if (undefined === transaction.Fee) {
if ('Payment' === transaction.TransactionType
&& transaction.Flags & Remote.flags.Payment.CreateAccount) {
@@ -980,6 +991,45 @@ Transaction.prototype.submit = function () {
// Set options for Transactions
//
+Transaction._path_rewrite = function (path) {
+ var path_new = [];
+
+ for (var index in path) {
+ var node = path[index];
+ var node_new = {};
+
+ if ('account' in node)
+ node_new.account = UInt160.json_rewrite(node.account);
+
+ if ('issuer' in node)
+ node_new.issuer = UInt160.json_rewrite(node.issuer);
+
+ if ('currency' in node)
+ node_new.currency = Currency.json_rewrite(node.currency);
+
+ path_new.push(node_new);
+ }
+
+ return path_new;
+}
+
+Transaction.prototype.path_add = function (path) {
+ this.transaction.Paths = this.transaction.Paths || []
+ this.transaction.Paths.push(Transaction._path_rewrite(path));
+
+ return this;
+}
+
+// --> paths: undefined or array of path
+// A path is an array of objects containing some combination of: account, currency, issuer
+Transaction.prototype.paths = function (paths) {
+ for (var index in paths) {
+ this.path_add(paths[index]);
+ }
+
+ return this;
+}
+
// If the secret is in the config object, it does not need to be provided.
Transaction.prototype.secret = function (secret) {
this.secret = secret;
@@ -987,7 +1037,7 @@ Transaction.prototype.secret = function (secret) {
Transaction.prototype.send_max = function (send_max) {
if (send_max)
- this.transaction.SendMax = send_max.to_json();
+ this.transaction.SendMax = Amount.json_rewrite(send_max);
return this;
}
@@ -1105,6 +1155,13 @@ Transaction.prototype.password_set = function (src, authorized_key, generator, p
// --> src : UInt160 or String
// --> dst : UInt160 or String
// --> deliver_amount : Amount or String.
+//
+// Options:
+// .paths()
+// .path_add()
+// .secret()
+// .send_max()
+// .set_flags()
Transaction.prototype.payment = function (src, dst, deliver_amount) {
this.secret = this._account_secret(src);
this.transaction.TransactionType = 'Payment';
diff --git a/newcoin.vcxproj b/newcoin.vcxproj
index a2dd3bbb6..3109a074a 100644
--- a/newcoin.vcxproj
+++ b/newcoin.vcxproj
@@ -112,6 +112,7 @@
+
diff --git a/src/Application.cpp b/src/Application.cpp
index 7c459fc12..758fae4ae 100644
--- a/src/Application.cpp
+++ b/src/Application.cpp
@@ -42,11 +42,13 @@ Application::Application() :
mNetOps(mIOService, &mMasterLedger), mTempNodeCache(16384, 90), mHashedObjectStore(16384, 300),
mSNTPClient(mAuxService), mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL),
mHashNodeDB(NULL), mNetNodeDB(NULL),
- mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
+ mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mSweepTimer(mAuxService)
{
RAND_bytes(mNonce256.begin(), mNonce256.size());
RAND_bytes(reinterpret_cast(&mNonceST), sizeof(mNonceST));
mJobQueue.setThreadCount();
+ mSweepTimer.expires_from_now(boost::posix_time::seconds(60));
+ mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
}
extern const char *RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[];
@@ -183,6 +185,16 @@ void Application::run()
std::cout << "Done." << std::endl;
}
+void Application::sweep()
+{
+ mMasterTransaction.sweep();
+ mHashedObjectStore.sweep();
+ mMasterLedger.sweep();
+ mTempNodeCache.sweep();
+ mSweepTimer.expires_from_now(boost::posix_time::seconds(60));
+ mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
+}
+
Application::~Application()
{
delete mTxnDB;
diff --git a/src/Application.h b/src/Application.h
index ebb078492..aeca10973 100644
--- a/src/Application.h
+++ b/src/Application.h
@@ -66,6 +66,8 @@ class Application
uint256 mNonce256;
std::size_t mNonceST;
+ boost::asio::deadline_timer mSweepTimer;
+
std::map mPeerMap;
boost::recursive_mutex mPeerMapLock;
@@ -93,8 +95,11 @@ public:
HashedObjectStore& getHashedObjectStore() { return mHashedObjectStore; }
ValidationCollection& getValidations() { return mValidations; }
JobQueue& getJobQueue() { return mJobQueue; }
+ SuppressionTable& getSuppression() { return mSuppressions; }
+
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
- bool isNew(const uint160& s) { return mSuppressions.addSuppression(s); }
+ bool isNew(const uint256& s, uint64 p) { return mSuppressions.addSuppressionPeer(s, p); }
+ bool isNewFlag(const uint256& s, int f) { return mSuppressions.setFlag(s, f); }
bool running() { return mTxnDB != NULL; }
bool getSystemTimeOffset(int& offset) { return mSNTPClient.getOffset(offset); }
@@ -110,6 +115,7 @@ public:
void run();
void stop();
+ void sweep();
};
extern Application* theApp;
diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp
index a6e1a9924..f95c0a970 100644
--- a/src/ConnectionPool.cpp
+++ b/src/ConnectionPool.cpp
@@ -29,6 +29,7 @@ void splitIpPort(const std::string& strIpPort, std::string& strIp, int& iPort)
}
ConnectionPool::ConnectionPool(boost::asio::io_service& io_service) :
+ mLastPeer(0),
mCtx(boost::asio::ssl::context::sslv23),
mScanTimer(io_service),
mPolicyTimer(io_service)
@@ -237,7 +238,7 @@ int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& m
BOOST_FOREACH(naPeer pair, mConnectedMap)
{
- Peer::pointer peer = pair.second;
+ Peer::ref peer = pair.second;
if (!peer)
std::cerr << "CP::RM null peer in list" << std::endl;
else if ((!fromPeer || !(peer.get() == fromPeer)) && peer->isConnected())
@@ -250,6 +251,32 @@ int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& m
return sentTo;
}
+void ConnectionPool::relayMessageBut(const std::set& fromPeers, const PackedMessage::pointer& msg)
+{ // Relay message to all but the specified peers
+ boost::mutex::scoped_lock sl(mPeerLock);
+
+ BOOST_FOREACH(naPeer pair, mConnectedMap)
+ {
+ Peer::ref peer = pair.second;
+ if (peer->isConnected() && (fromPeers.count(peer->getPeerId()) == 0))
+ peer->sendPacket(msg);
+ }
+
+}
+
+void ConnectionPool::relayMessageTo(const std::set& fromPeers, const PackedMessage::pointer& msg)
+{ // Relay message to the specified peers
+ boost::mutex::scoped_lock sl(mPeerLock);
+
+ BOOST_FOREACH(naPeer pair, mConnectedMap)
+ {
+ Peer::ref peer = pair.second;
+ if (peer->isConnected() && (fromPeers.count(peer->getPeerId()) > 0))
+ peer->sendPacket(msg);
+ }
+
+}
+
// Schedule a connection via scanning.
//
// Add or modify into PeerIps as a manual entry for immediate scanning.
@@ -354,6 +381,12 @@ std::vector ConnectionPool::getPeerVector()
return ret;
}
+uint64 ConnectionPool::assignPeerId()
+{
+ boost::mutex::scoped_lock sl(mPeerLock);
+ return ++mLastPeer;
+}
+
// Now know peer's node public key. Determine if we want to stay connected.
// <-- bNew: false = redundant
bool ConnectionPool::peerConnected(Peer::ref peer, const RippleAddress& naPeer,
diff --git a/src/ConnectionPool.h b/src/ConnectionPool.h
index 1b909f626..e3801ef73 100644
--- a/src/ConnectionPool.h
+++ b/src/ConnectionPool.h
@@ -1,6 +1,8 @@
#ifndef __CONNECTION_POOL__
#define __CONNECTION_POOL__
+#include
+
#include
#include
@@ -14,7 +16,8 @@
class ConnectionPool
{
private:
- boost::mutex mPeerLock;
+ boost::mutex mPeerLock;
+ uint64 mLastPeer;
typedef std::pair naPeer;
typedef std::pair pipPeer;
@@ -59,6 +62,8 @@ public:
// Send message to network.
int relayMessage(Peer* fromPeer, const PackedMessage::pointer& msg);
+ void relayMessageTo(const std::set& fromPeers, const PackedMessage::pointer& msg);
+ void relayMessageBut(const std::set& fromPeers, const PackedMessage::pointer& msg);
// Manual connection request.
// Queue for immediate scanning.
@@ -87,6 +92,9 @@ public:
Json::Value getPeersJson();
std::vector getPeerVector();
+ // Peer 64-bit ID function
+ uint64 assignPeerId();
+
//
// Scanning
//
diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp
index 997be4c23..bff9c34c6 100644
--- a/src/HashedObject.cpp
+++ b/src/HashedObject.cpp
@@ -9,6 +9,7 @@
#include "Log.h"
SETUP_LOG();
+DECLARE_INSTANCE(HashedObject);
HashedObjectStore::HashedObjectStore(int cacheSize, int cacheAge) :
mCache(cacheSize, cacheAge), mWritePending(false)
diff --git a/src/HashedObject.h b/src/HashedObject.h
index 5178af089..7f3191254 100644
--- a/src/HashedObject.h
+++ b/src/HashedObject.h
@@ -10,6 +10,9 @@
#include "uint256.h"
#include "ScopedLock.h"
#include "TaggedCache.h"
+#include "InstanceCounter.h"
+
+DEFINE_INSTANCE(HashedObject);
enum HashedObjectType
{
@@ -20,7 +23,7 @@ enum HashedObjectType
hotTRANSACTION_NODE = 4
};
-class HashedObject
+class HashedObject : private IS_INSTANCE(HashedObject)
{
public:
typedef boost::shared_ptr pointer;
@@ -61,6 +64,7 @@ public:
void bulkWrite();
void waitWrite();
+ void sweep() { mCache.sweep(); }
};
#endif
diff --git a/src/InstanceCounter.cpp b/src/InstanceCounter.cpp
new file mode 100644
index 000000000..564010282
--- /dev/null
+++ b/src/InstanceCounter.cpp
@@ -0,0 +1,15 @@
+#include "InstanceCounter.h"
+
+InstanceType* InstanceType::sHeadInstance = NULL;
+
+std::vector InstanceType::getInstanceCounts(int min)
+{
+ std::vector ret;
+ for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
+ {
+ int c = i->getCount();
+ if (c >= min)
+ ret.push_back(InstanceCount(i->getName(), c));
+ }
+ return ret;
+}
diff --git a/src/InstanceCounter.h b/src/InstanceCounter.h
new file mode 100644
index 000000000..ffb3665f5
--- /dev/null
+++ b/src/InstanceCounter.h
@@ -0,0 +1,80 @@
+#ifndef INSTANCE_COUNTER__H
+#define INSTANCE_COUNTER__H
+
+#include
+#include
+
+#include
+
+#define DEFINE_INSTANCE(x) \
+ extern InstanceType IT_##x; \
+ class Instance_##x : private Instance \
+ { \
+ protected: \
+ Instance_##x() : Instance(IT_##x) { ; } \
+ Instance_##x(const Instance_##x &) : \
+ Instance(IT_##x) { ; } \
+ Instance_##x& operator=(const Instance_##x&) \
+ { return *this; } \
+ }
+
+#define DECLARE_INSTANCE(x) \
+ InstanceType IT_##x(#x);
+
+#define IS_INSTANCE(x) Instance_##x
+
+class InstanceType
+{
+protected:
+ int mInstances;
+ std::string mName;
+ boost::mutex mLock;
+
+ InstanceType* mNextInstance;
+ static InstanceType* sHeadInstance;
+
+public:
+ typedef std::pair InstanceCount;
+
+ InstanceType(const char *n) : mInstances(0), mName(n)
+ {
+ mNextInstance = sHeadInstance;
+ sHeadInstance = this;
+ }
+
+ void addInstance()
+ {
+ mLock.lock();
+ ++mInstances;
+ mLock.unlock();
+ }
+ void decInstance()
+ {
+ mLock.lock();
+ --mInstances;
+ mLock.unlock();
+ }
+ int getCount()
+ {
+ boost::mutex::scoped_lock(mLock);
+ return mInstances;
+ }
+ const std::string& getName()
+ {
+ return mName;
+ }
+
+ static std::vector getInstanceCounts(int min = 1);
+};
+
+class Instance
+{
+protected:
+ InstanceType& mType;
+
+public:
+ Instance(InstanceType& t) : mType(t) { mType.addInstance(); }
+ ~Instance() { mType.decInstance(); }
+};
+
+#endif
diff --git a/src/Ledger.cpp b/src/Ledger.cpp
index 1b6775232..ec44a5dc9 100644
--- a/src/Ledger.cpp
+++ b/src/Ledger.cpp
@@ -20,6 +20,7 @@
#include "Log.h"
SETUP_LOG();
+DECLARE_INSTANCE(Ledger);
Ledger::Ledger(const RippleAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(1),
mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0),
@@ -1072,7 +1073,7 @@ int Ledger::getPendingSaves()
void Ledger::pendSave(bool fromConsensus)
{
- if (!fromConsensus && !theApp->isNew(getHash()))
+ if (!fromConsensus && !theApp->isNewFlag(getHash(), SF_SAVED))
return;
boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, shared_from_this(), fromConsensus));
diff --git a/src/Ledger.h b/src/Ledger.h
index 1074ec9fb..c033c59c4 100644
--- a/src/Ledger.h
+++ b/src/Ledger.h
@@ -18,6 +18,7 @@
#include "types.h"
#include "BitcoinUtil.h"
#include "SHAMap.h"
+#include "InstanceCounter.h"
enum LedgerStateParms
{
@@ -38,7 +39,9 @@ enum LedgerStateParms
#define LEDGER_JSON_DUMP_STATE 0x20000000
#define LEDGER_JSON_FULL 0x40000000
-class Ledger : public boost::enable_shared_from_this
+DEFINE_INSTANCE(Ledger);
+
+class Ledger : public boost::enable_shared_from_this, public IS_INSTANCE(Ledger)
{ // The basic Ledger structure, can be opened, closed, or synching
friend class TransactionEngine;
public:
diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp
index beeaaa400..9f55c2243 100644
--- a/src/LedgerConsensus.cpp
+++ b/src/LedgerConsensus.cpp
@@ -845,7 +845,7 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec
txn->setVote(pit.first, cit->second->hasItem(txID));
}
- if (!ourVote && theApp->isNew(txID))
+ if (!ourVote && theApp->isNewFlag(txID, SF_RELAYED))
{
ripple::TMTransaction msg;
msg.set_rawtransaction(&(tx.front()), tx.size());
diff --git a/src/LedgerHistory.h b/src/LedgerHistory.h
index ed58f4fc9..51ecaf714 100644
--- a/src/LedgerHistory.h
+++ b/src/LedgerHistory.h
@@ -18,6 +18,7 @@ public:
Ledger::pointer getLedgerBySeq(uint32 index);
Ledger::pointer getLedgerByHash(const uint256& hash);
Ledger::pointer canonicalizeLedger(Ledger::pointer, bool cache);
+ void sweep() { mLedgersByHash.sweep(); }
};
#endif
diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h
index 967026fed..e3270710e 100644
--- a/src/LedgerMaster.h
+++ b/src/LedgerMaster.h
@@ -91,6 +91,8 @@ public:
void setLedgerRangePresent(uint32 minV, uint32 maxV) { mCompleteLedgers.setRange(minV, maxV); }
bool addHeldTransaction(const Transaction::pointer& trans);
+
+ void sweep(void) { mLedgerHistory.sweep(); }
};
#endif
diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp
index dbeb8fd1d..7bb4c6705 100644
--- a/src/NetworkOPs.cpp
+++ b/src/NetworkOPs.cpp
@@ -88,22 +88,31 @@ Transaction::pointer NetworkOPs::submitTransaction(const Transaction::pointer& t
tpTrans->getSTransaction()->add(s);
Transaction::pointer tpTransNew = Transaction::sharedTransaction(s.getData(), true);
- assert(tpTransNew);
- if(!tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction()))
+ if (!tpTransNew)
+ {
+ // Could not construct transaction.
+ nothing();
+ }
+ else if (tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction()))
+ {
+ (void) NetworkOPs::processTransaction(tpTransNew);
+ }
+ else
{
cLog(lsFATAL) << "Transaction reconstruction failure";
cLog(lsFATAL) << tpTransNew->getSTransaction()->getJson(0);
cLog(lsFATAL) << tpTrans->getSTransaction()->getJson(0);
- assert(false);
- }
- (void) NetworkOPs::processTransaction(tpTransNew);
+ assert(false);
+
+ tpTransNew = Transaction::pointer();
+ }
return tpTransNew;
}
-Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, Peer* source)
+Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans)
{
Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true);
if (dbtx) return dbtx;
@@ -151,27 +160,28 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
trans->setStatus(INCLUDED);
theApp->getMasterTransaction().canonicalize(trans, true);
-// FIXME: Need code to get all accounts affected by a transaction and re-synch
-// any of them that affect local accounts cached in memory. Or, we need to
-// no cache the account balance information and always get it from the current ledger
-// theApp->getWallet().applyTransaction(trans);
+ std::set peers;
+ if (theApp->getSuppression().swapSet(trans->getID(), peers, SF_RELAYED))
+ {
+ ripple::TMTransaction tx;
+ Serializer s;
+ trans->getSTransaction()->add(s);
+ tx.set_rawtransaction(&s.getData().front(), s.getLength());
+ tx.set_status(ripple::tsCURRENT);
+ tx.set_receivetimestamp(getNetworkTimeNC());
- ripple::TMTransaction tx;
- Serializer s;
- trans->getSTransaction()->add(s);
- tx.set_rawtransaction(&s.getData().front(), s.getLength());
- tx.set_status(ripple::tsCURRENT);
- tx.set_receivetimestamp(getNetworkTimeNC());
-
- PackedMessage::pointer packet = boost::make_shared(tx, ripple::mtTRANSACTION);
- int sentTo = theApp->getConnectionPool().relayMessage(source, packet);
- cLog(lsINFO) << "Transaction relayed to " << sentTo << " node(s)";
+ PackedMessage::pointer packet = boost::make_shared(tx, ripple::mtTRANSACTION);
+ theApp->getConnectionPool().relayMessageBut(peers, packet);
+ }
return trans;
}
cLog(lsDEBUG) << "Status other than success " << r;
- if ((mMode != omFULL) && (mMode != omTRACKING) && (theApp->isNew(trans->getID())))
+ std::set peers;
+
+ if ((mMode != omFULL) && (mMode != omTRACKING) &&
+ theApp->getSuppression().swapSet(trans->getID(), peers, SF_RELAYED))
{
ripple::TMTransaction tx;
Serializer s;
@@ -180,7 +190,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
tx.set_status(ripple::tsCURRENT);
tx.set_receivetimestamp(getNetworkTimeNC());
PackedMessage::pointer packet = boost::make_shared(tx, ripple::mtTRANSACTION);
- theApp->getConnectionPool().relayMessage(source, packet);
+ theApp->getConnectionPool().relayMessageTo(peers, packet);
}
trans->setStatus(INVALID);
@@ -685,7 +695,7 @@ bool NetworkOPs::haveConsensusObject()
}
// <-- bool: true to relay
-bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger,
+bool NetworkOPs::recvPropose(uint64 peerId, uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger,
uint32 closeTime, const std::string& pubKey, const std::string& signature, const RippleAddress& nodePublic)
{
// JED: does mConsensus need to be locked?
@@ -701,7 +711,7 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, cons
s.add32(closeTime);
s.addRaw(pubKey);
s.addRaw(signature);
- if (!theApp->isNew(s.getSHA512Half()))
+ if (!theApp->isNew(s.getSHA512Half(), peerId))
return false;
RippleAddress naPeerPublic = RippleAddress::createNodePublic(strCopy(pubKey));
diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h
index 2ee052478..0e8a88f10 100644
--- a/src/NetworkOPs.h
+++ b/src/NetworkOPs.h
@@ -124,7 +124,7 @@ public:
//
Transaction::pointer submitTransaction(const Transaction::pointer& tpTrans);
- Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source = NULL);
+ Transaction::pointer processTransaction(Transaction::pointer transaction);
Transaction::pointer findTransactionByID(const uint256& transactionID);
int findTransactionsBySource(const uint256& uLedger, std::list&, const RippleAddress& sourceAccount,
uint32 minSeq, uint32 maxSeq);
@@ -171,8 +171,8 @@ public:
const std::vector& myNode, std::list< std::vector >& newNodes);
// ledger proposal/close functions
- bool recvPropose(uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger, uint32 closeTime,
- const std::string& pubKey, const std::string& signature, const RippleAddress& nodePublic);
+ bool recvPropose(uint64 peerId, uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger,
+ uint32 closeTime, const std::string& pubKey, const std::string& signature, const RippleAddress& nodePublic);
bool gotTXData(const boost::shared_ptr& peer, const uint256& hash,
const std::list& nodeIDs, const std::list< std::vector >& nodeData);
bool recvValidation(const SerializedValidation::pointer& val);
diff --git a/src/Peer.cpp b/src/Peer.cpp
index 609bf90e5..d441876dc 100644
--- a/src/Peer.cpp
+++ b/src/Peer.cpp
@@ -16,6 +16,7 @@
#include "Log.h"
SETUP_LOG();
+DECLARE_INSTANCE(Peer);
// Don't try to run past receiving nonsense from a peer
#define TRUST_NETWORK
@@ -29,7 +30,8 @@ Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
mSocketSsl(io_service, ctx),
mVerifyTimer(io_service)
{
- // cLog(lsDEBUG) << "CREATING PEER: " << ADDRESS(this);
+ cLog(lsDEBUG) << "CREATING PEER: " << ADDRESS(this);
+ mPeerId = theApp->getConnectionPool().assignPeerId();
}
void Peer::handle_write(const boost::system::error_code& error, size_t bytes_transferred)
@@ -706,8 +708,12 @@ void Peer::recvTransaction(ripple::TMTransaction& packet)
SerializerIterator sit(s);
SerializedTransaction::pointer stx = boost::make_shared(boost::ref(sit));
+ if (!theApp->isNew(stx->getTransactionID(), mPeerId))
+ return;
+
tx = boost::make_shared(stx, true);
- if (tx->getStatus() == INVALID) throw(0);
+ if (tx->getStatus() == INVALID)
+ throw(0);
#ifndef TRUST_NETWORK
}
catch (...)
@@ -721,7 +727,7 @@ void Peer::recvTransaction(ripple::TMTransaction& packet)
}
#endif
- tx = theApp->getOPs().processTransaction(tx, this);
+ tx = theApp->getOPs().processTransaction(tx);
if(tx->getStatus() != INCLUDED)
{ // transaction wasn't accepted into ledger
@@ -746,7 +752,7 @@ void Peer::recvPropose(ripple::TMProposeSet& packet)
if ((packet.has_previousledger()) && (packet.previousledger().size() == 32))
memcpy(prevLedger.begin(), packet.previousledger().data(), 32);
- if(theApp->getOPs().recvPropose(packet.proposeseq(), currentTxHash, prevLedger, packet.closetime(),
+ if(theApp->getOPs().recvPropose(mPeerId, packet.proposeseq(), currentTxHash, prevLedger, packet.closetime(),
packet.nodepubkey(), packet.signature(), mNodePublic))
{ // FIXME: Not all nodes will want proposals
PackedMessage::pointer message = boost::make_shared(packet, ripple::mtPROPOSE_LEDGER);
@@ -820,7 +826,7 @@ void Peer::recvValidation(const boost::shared_ptr& packet)
SerializedValidation::pointer val = boost::make_shared(boost::ref(sit), false);
uint256 signingHash = val->getSigningHash();
- if (!theApp->isNew(signingHash))
+ if (!theApp->isNew(signingHash, mPeerId))
{
cLog(lsTRACE) << "Validation is duplicate";
return;
diff --git a/src/Peer.h b/src/Peer.h
index 76b11d092..49857e3e6 100644
--- a/src/Peer.h
+++ b/src/Peer.h
@@ -11,6 +11,7 @@
#include "PackedMessage.h"
#include "Ledger.h"
#include "Transaction.h"
+#include "InstanceCounter.h"
enum PeerPunish
{
@@ -21,7 +22,9 @@ enum PeerPunish
typedef std::pair ipPort;
-class Peer : public boost::enable_shared_from_this
+DEFINE_INSTANCE(Peer);
+
+class Peer : public boost::enable_shared_from_this, public IS_INSTANCE(Peer)
{
public:
typedef boost::shared_ptr pointer;
@@ -43,6 +46,7 @@ private:
ipPort mIpPort;
ipPort mIpPortConnect;
uint256 mCookieHash;
+ uint64 mPeerId;
uint256 mClosedLedgerHash, mPreviousLedgerHash;
std::list mRecentLedgers;
@@ -159,6 +163,8 @@ public:
uint256 getClosedLedgerHash() const { return mClosedLedgerHash; }
bool hasLedger(const uint256& hash) const;
bool hasTxSet(const uint256& hash) const;
+ uint64 getPeerId() const { return mPeerId; }
+
RippleAddress getNodePublic() const { return mNodePublic; }
void cycleStatus() { mPreviousLedgerHash = mClosedLedgerHash; mClosedLedgerHash.zero(); }
};
diff --git a/src/RPCHandler.cpp b/src/RPCHandler.cpp
index 2b8fe7225..36fcfdffd 100644
--- a/src/RPCHandler.cpp
+++ b/src/RPCHandler.cpp
@@ -7,6 +7,7 @@
#include "RippleAddress.h"
#include "AccountState.h"
#include "NicknameState.h"
+#include "InstanceCounter.h"
#include "Pathfinder.h"
#include
@@ -75,7 +76,7 @@ Json::Value RPCHandler::rpcError(int iError)
for (i=NUMBER(errorInfoA); i-- && errorInfoA[i].iError != iError;)
;
- Json::Value jsonResult = Json::Value(Json::objectValue);
+ Json::Value jsonResult(Json::objectValue);
jsonResult["error"] = i >= 0 ? errorInfoA[i].pToken : lexical_cast_i(iError);
jsonResult["error_message"] = i >= 0 ? errorInfoA[i].pMessage : lexical_cast_i(iError);
@@ -2420,37 +2421,38 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
bool mAdminRequired;
unsigned int iOptions;
} commandsA[] = {
- { "accept_ledger", &RPCHandler::doAcceptLedger, 0, 0, true },
- { "account_domain_set", &RPCHandler::doAccountDomainSet, 2, 3, false, optCurrent },
+ { "accept_ledger", &RPCHandler::doAcceptLedger, 0, 0, true },
+ { "account_domain_set", &RPCHandler::doAccountDomainSet, 2, 3, false, optCurrent },
{ "account_email_set", &RPCHandler::doAccountEmailSet, 2, 3, false, optCurrent },
{ "account_info", &RPCHandler::doAccountInfo, 1, 2, false, optCurrent },
{ "account_message_set", &RPCHandler::doAccountMessageSet, 3, 3, false, optCurrent },
{ "account_publish_set", &RPCHandler::doAccountPublishSet, 4, 4, false, optCurrent },
{ "account_rate_set", &RPCHandler::doAccountRateSet, 3, 3, false, optCurrent },
{ "account_tx", &RPCHandler::doAccountTransactions, 2, 3, false, optNetwork },
- { "account_wallet_set", &RPCHandler::doAccountWalletSet, 2, 3, false, optCurrent },
+ { "account_wallet_set", &RPCHandler::doAccountWalletSet, 2, 3, false, optCurrent },
{ "connect", &RPCHandler::doConnect, 1, 2, true },
{ "data_delete", &RPCHandler::doDataDelete, 1, 1, true },
{ "data_fetch", &RPCHandler::doDataFetch, 1, 1, true },
{ "data_store", &RPCHandler::doDataStore, 2, 2, true },
+ { "get_counts", &RPCHandler::doGetCounts, 0, 1, true },
{ "ledger", &RPCHandler::doLedger, 0, 2, false, optNetwork },
- { "log_level", &RPCHandler::doLogLevel, 0, 2, true },
+ { "log_level", &RPCHandler::doLogLevel, 0, 2, true },
{ "logrotate", &RPCHandler::doLogRotate, 0, 0, true },
- { "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, optCurrent },
+ { "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, optCurrent },
{ "nickname_set", &RPCHandler::doNicknameSet, 2, 3, false, optCurrent },
{ "offer_create", &RPCHandler::doOfferCreate, 9, 10, false, optCurrent },
{ "offer_cancel", &RPCHandler::doOfferCancel, 3, 3, false, optCurrent },
{ "owner_info", &RPCHandler::doOwnerInfo, 1, 2, false, optCurrent },
- { "password_fund", &RPCHandler::doPasswordFund, 2, 3, false, optCurrent },
+ { "password_fund", &RPCHandler::doPasswordFund, 2, 3, false, optCurrent },
{ "password_set", &RPCHandler::doPasswordSet, 2, 3, false, optNetwork },
{ "peers", &RPCHandler::doPeers, 0, 0, true },
{ "profile", &RPCHandler::doProfile, 1, 9, false, optCurrent },
{ "ripple", &RPCHandler::doRipple, 9, -1, false, optCurrent|optClosed },
{ "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, false, optCurrent },
{ "ripple_line_set", &RPCHandler::doRippleLineSet, 4, 7, false, optCurrent },
- { "send", &RPCHandler::doSend, 3, 9, false, optCurrent },
+ { "send", &RPCHandler::doSend, 3, 9, false, optCurrent },
{ "server_info", &RPCHandler::doServerInfo, 0, 0, true },
- { "stop", &RPCHandler::doStop, 0, 0, true },
+ { "stop", &RPCHandler::doStop, 0, 0, true },
{ "tx", &RPCHandler::doTx, 1, 1, true },
{ "tx_history", &RPCHandler::doTxHistory, 1, 1, false, },
@@ -2459,16 +2461,16 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
{ "unl_list", &RPCHandler::doUnlList, 0, 0, true },
{ "unl_load", &RPCHandler::doUnlLoad, 0, 0, true },
{ "unl_network", &RPCHandler::doUnlNetwork, 0, 0, true },
- { "unl_reset", &RPCHandler::doUnlReset, 0, 0, true },
- { "unl_score", &RPCHandler::doUnlScore, 0, 0, true },
+ { "unl_reset", &RPCHandler::doUnlReset, 0, 0, true },
+ { "unl_score", &RPCHandler::doUnlScore, 0, 0, true },
- { "validation_create", &RPCHandler::doValidationCreate, 0, 1, false },
+ { "validation_create", &RPCHandler::doValidationCreate, 0, 1, false },
{ "validation_seed", &RPCHandler::doValidationSeed, 0, 1, false },
{ "wallet_accounts", &RPCHandler::doWalletAccounts, 1, 1, false, optCurrent },
{ "wallet_add", &RPCHandler::doWalletAdd, 3, 5, false, optCurrent },
{ "wallet_claim", &RPCHandler::doWalletClaim, 2, 4, false, optNetwork },
- { "wallet_create", &RPCHandler::doWalletCreate, 3, 4, false, optCurrent },
+ { "wallet_create", &RPCHandler::doWalletCreate, 3, 4, false, optCurrent },
{ "wallet_propose", &RPCHandler::doWalletPropose, 0, 1, false, },
{ "wallet_seed", &RPCHandler::doWalletSeed, 0, 1, false, },
@@ -2603,6 +2605,20 @@ Json::Value RPCHandler::doLogin(const Json::Value& params)
}
}
+Json::Value RPCHandler::doGetCounts(const Json::Value& params)
+{
+ int minCount = 1;
+ if (params.size() > 0)
+ minCount = params[0u].asInt();
+
+ std::vector count = InstanceType::getInstanceCounts(minCount);
+
+ Json::Value ret(Json::objectValue);
+ BOOST_FOREACH(InstanceType::InstanceCount& it, count)
+ ret[it.first] = it.second;
+ return ret;
+}
+
Json::Value RPCHandler::doLogLevel(const Json::Value& params)
{
if (params.size() == 0)
diff --git a/src/RPCHandler.h b/src/RPCHandler.h
index 4dfd7f80b..c001e7dff 100644
--- a/src/RPCHandler.h
+++ b/src/RPCHandler.h
@@ -1,3 +1,6 @@
+#ifndef RPCHANDLER__H
+#define RPCHANDLER__H
+
// used by the RPCServer or WSDoor to carry out these RPC commands
class NetworkOPs;
@@ -37,6 +40,7 @@ class RPCHandler
Json::Value doDataDelete(const Json::Value& params);
Json::Value doDataFetch(const Json::Value& params);
Json::Value doDataStore(const Json::Value& params);
+ Json::Value doGetCounts(const Json::Value& params);
Json::Value doLedger(const Json::Value& params);
Json::Value doLogRotate(const Json::Value& params);
Json::Value doNicknameInfo(const Json::Value& params);
@@ -156,4 +160,6 @@ public:
Json::Value doCommand(const std::string& command, Json::Value& params,int role);
Json::Value rpcError(int iError);
-};
\ No newline at end of file
+};
+
+#endif
diff --git a/src/RippleCalc.cpp b/src/RippleCalc.cpp
index 6cbbf46d8..3d14717d8 100644
--- a/src/RippleCalc.cpp
+++ b/src/RippleCalc.cpp
@@ -1421,6 +1421,8 @@ bool PathState::lessPriority(PathState::ref lhs, PathState::ref rhs)
// Make sure the path delivers to uAccountID: uCurrencyID from uIssuerID.
//
+// If the unadded next node as specified by arguments would not work as is, then add the necessary nodes so it would work.
+//
// Rules:
// - Currencies must be converted via an offer.
// - A node names it's output.
@@ -1449,13 +1451,14 @@ TER PathState::pushImply(
ACCOUNT_ONE, // Placeholder for offers.
uCurrencyID, // The offer's output is what is now wanted.
uIssuerID);
-
}
+ const PaymentNode& pnBck = vpnNodes.back();
+
// For ripple, non-stamps, ensure the issuer is on at least one side of the transaction.
if (tesSUCCESS == terResult
&& !!uCurrencyID // Not stamps.
- && (pnPrv.uAccountID != uIssuerID // Previous is not issuing own IOUs.
+ && (pnBck.uAccountID != uIssuerID // Previous is not issuing own IOUs.
&& uAccountID != uIssuerID)) // Current is not receiving own IOUs.
{
// Need to ripple through uIssuerID's account.
@@ -1514,13 +1517,19 @@ TER PathState::pushNode(
pnCur.saRevRedeem = STAmount(uCurrencyID, uAccountID);
pnCur.saRevIssue = STAmount(uCurrencyID, uAccountID);
- if (!bFirst)
+ if (bFirst)
+ {
+ // The first node is always correct as is.
+
+ nothing();
+ }
+ else
{
// Add required intermediate nodes to deliver to current account.
terResult = pushImply(
pnCur.uAccountID, // Current account.
pnCur.uCurrencyID, // Wanted currency.
- !!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as issuer.
+ !!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as wanted issuer.
// Note: pnPrv may no longer be the immediately previous node.
}
@@ -1532,7 +1541,7 @@ TER PathState::pushNode(
if (bBckAccount)
{
- SLE::pointer sleRippleState = mLedger->getSLE(Ledger::getRippleStateIndex(pnBck.uAccountID, pnCur.uAccountID, pnPrv.uCurrencyID));
+ SLE::pointer sleRippleState = lesEntries.entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(pnBck.uAccountID, pnCur.uAccountID, pnPrv.uCurrencyID));
if (!sleRippleState)
{
@@ -1541,7 +1550,7 @@ TER PathState::pushNode(
<< " and "
<< RippleAddress::createHumanAccountID(pnCur.uAccountID)
<< " for "
- << STAmount::createHumanCurrency(pnPrv.uCurrencyID)
+ << STAmount::createHumanCurrency(pnCur.uCurrencyID)
<< "." ;
cLog(lsINFO) << getJson();
@@ -1555,12 +1564,12 @@ TER PathState::pushNode(
<< " and "
<< RippleAddress::createHumanAccountID(pnCur.uAccountID)
<< " for "
- << STAmount::createHumanCurrency(pnPrv.uCurrencyID)
+ << STAmount::createHumanCurrency(pnCur.uCurrencyID)
<< "." ;
- STAmount saOwed = lesEntries.rippleOwed(pnCur.uAccountID, pnBck.uAccountID, uCurrencyID);
+ STAmount saOwed = lesEntries.rippleOwed(pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID);
- if (!saOwed.isPositive() && *saOwed.negate() >= lesEntries.rippleLimit(pnCur.uAccountID, pnBck.uAccountID, uCurrencyID))
+ if (!saOwed.isPositive() && *saOwed.negate() >= lesEntries.rippleLimit(pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID))
{
terResult = tepPATH_DRY;
}
diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp
index b7a775778..e3de616d2 100644
--- a/src/SHAMap.cpp
+++ b/src/SHAMap.cpp
@@ -17,6 +17,10 @@
SETUP_LOG();
+DECLARE_INSTANCE(SHAMap);
+DECLARE_INSTANCE(SHAMapItem);
+DECLARE_INSTANCE(SHAMapTreeNode);
+
std::size_t hash_value(const SHAMapNode& mn)
{
std::size_t seed = theApp->getNonceST();
diff --git a/src/SHAMap.h b/src/SHAMap.h
index 107d3d8b6..6acadf667 100644
--- a/src/SHAMap.h
+++ b/src/SHAMap.h
@@ -14,6 +14,11 @@
#include "ScopedLock.h"
#include "Serializer.h"
#include "HashedObject.h"
+#include "InstanceCounter.h"
+
+DEFINE_INSTANCE(SHAMap);
+DEFINE_INSTANCE(SHAMapItem);
+DEFINE_INSTANCE(SHAMapTreeNode);
class SHAMap;
@@ -31,7 +36,7 @@ private:
public:
- static const int rootDepth=0;
+ static const int rootDepth = 0;
SHAMapNode() : mDepth(0) { ; }
SHAMapNode(int depth, const uint256& hash);
@@ -77,7 +82,7 @@ extern std::size_t hash_value(const SHAMapNode& mn);
inline std::ostream& operator<<(std::ostream& out, const SHAMapNode& node) { return out << node.getString(); }
-class SHAMapItem
+class SHAMapItem : public IS_INSTANCE(SHAMapItem)
{ // an item stored in a SHAMap
public:
typedef boost::shared_ptr pointer;
@@ -135,7 +140,7 @@ enum SHAMapType
smtFREE =3, // A tree not part of a ledger
};
-class SHAMapTreeNode : public SHAMapNode
+class SHAMapTreeNode : public SHAMapNode, public IS_INSTANCE(SHAMapTreeNode)
{
friend class SHAMap;
@@ -276,7 +281,7 @@ public:
extern std::ostream& operator<<(std::ostream&, const SHAMapMissingNode&);
-class SHAMap
+class SHAMap : public IS_INSTANCE(SHAMap)
{
public:
typedef boost::shared_ptr pointer;
diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp
index 359a93fa5..00a353987 100644
--- a/src/SerializedLedger.cpp
+++ b/src/SerializedLedger.cpp
@@ -5,6 +5,8 @@
#include "Ledger.h"
#include "Log.h"
+DECLARE_INSTANCE(SerializedLedgerEntry)
+
SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index)
: STObject(sfLedgerEntry), mIndex(index)
{
diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h
index c02126db1..7bbdfaf99 100644
--- a/src/SerializedLedger.h
+++ b/src/SerializedLedger.h
@@ -4,8 +4,11 @@
#include "SerializedObject.h"
#include "LedgerFormats.h"
#include "RippleAddress.h"
+#include "InstanceCounter.h"
-class SerializedLedgerEntry : public STObject
+DEFINE_INSTANCE(SerializedLedgerEntry);
+
+class SerializedLedgerEntry : public STObject, private IS_INSTANCE(SerializedLedgerEntry)
{
public:
typedef boost::shared_ptr pointer;
diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp
index 1477a2393..2f90c75cb 100644
--- a/src/SerializedObject.cpp
+++ b/src/SerializedObject.cpp
@@ -14,6 +14,8 @@
#include "SerializedTransaction.h"
SETUP_LOG();
+DECLARE_INSTANCE(SerializedObject);
+DECLARE_INSTANCE(SerializedArray);
std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, SField::ref name)
{
@@ -1110,23 +1112,24 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r
data.push_back(new STPathSet(field));
STPathSet* tail = dynamic_cast(&data.back());
assert(tail);
- for (Json::UInt i = 0; !object.isValidIndex(i); ++i)
+ for (Json::UInt i = 0; value.isValidIndex(i); ++i)
{
STPath p;
- if (!object[i].isArray())
+ if (!value[i].isArray())
throw std::runtime_error("Path must be array");
- for (Json::UInt j = 0; !object[i].isValidIndex(j); ++j)
+ for (Json::UInt j = 0; value[i].isValidIndex(j); ++j)
{ // each element in this path has some combination of account, currency, or issuer
- Json::Value pathEl = object[i][j];
+ Json::Value pathEl = value[i][j];
if (!pathEl.isObject())
throw std::runtime_error("Path elements must be objects");
- const Json::Value& account = pathEl["account"];
- const Json::Value& currency = pathEl["currency"];
- const Json::Value& issuer = pathEl["issuer"];
+ const Json::Value& account = pathEl["account"];
+ const Json::Value& currency = pathEl["currency"];
+ const Json::Value& issuer = pathEl["issuer"];
+ bool hasCurrency = false;
uint160 uAccount, uCurrency, uIssuer;
- bool hasCurrency;
+
if (!account.isNull())
{ // human account id
if (!account.isString())
@@ -1136,7 +1139,7 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r
uAccount.SetHex(strValue);
{
RippleAddress a;
- if (!a.setAccountPublic(strValue))
+ if (!a.setAccountID(strValue))
throw std::runtime_error("Account in path element invalid");
uAccount = a.getAccountID();
}
@@ -1160,7 +1163,7 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r
else
{
RippleAddress a;
- if (!a.setAccountPublic(issuer.asString()))
+ if (!a.setAccountID(issuer.asString()))
throw std::runtime_error("path element issuer invalid");
uIssuer = a.getAccountID();
}
diff --git a/src/SerializedObject.h b/src/SerializedObject.h
index 00c89ed1e..d0d3ce6af 100644
--- a/src/SerializedObject.h
+++ b/src/SerializedObject.h
@@ -8,6 +8,10 @@
#include "../json/value.h"
#include "SerializedTypes.h"
+#include "InstanceCounter.h"
+
+DEFINE_INSTANCE(SerializedObject);
+DEFINE_INSTANCE(SerializedArray);
// Serializable object/array types
@@ -22,7 +26,7 @@ public:
SOElement(SField::ref fi, SOE_Flags fl) : e_field(fi), flags(fl) { ; }
};
-class STObject : public SerializedType
+class STObject : public SerializedType, private IS_INSTANCE(SerializedObject)
{
protected:
boost::ptr_vector mData;
@@ -175,7 +179,7 @@ namespace boost
-class STArray : public SerializedType
+class STArray : public SerializedType, private IS_INSTANCE(SerializedArray)
{
public:
typedef std::vector vector;
diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp
index d6b7a0291..bdc26d77e 100644
--- a/src/SerializedTransaction.cpp
+++ b/src/SerializedTransaction.cpp
@@ -8,6 +8,8 @@
#include "Log.h"
#include "HashPrefixes.h"
+DECLARE_INSTANCE(SerializedTransaction);
+
SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type)
{
mFormat = TransactionFormat::getTxnFormat(type);
diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h
index 185ca6cda..50d974db0 100644
--- a/src/SerializedTransaction.h
+++ b/src/SerializedTransaction.h
@@ -9,6 +9,7 @@
#include "SerializedObject.h"
#include "TransactionFormats.h"
#include "RippleAddress.h"
+#include "InstanceCounter.h"
#define TXN_SQL_NEW 'N'
#define TXN_SQL_CONFLICT 'C'
@@ -17,7 +18,9 @@
#define TXN_SQL_INCLUDED 'I'
#define TXN_SQL_UNKNOWN 'U'
-class SerializedTransaction : public STObject
+DEFINE_INSTANCE(SerializedTransaction);
+
+class SerializedTransaction : public STObject, private IS_INSTANCE(SerializedTransaction)
{
public:
typedef boost::shared_ptr pointer;
diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp
index 55fc7039b..61f526eeb 100644
--- a/src/SerializedTypes.cpp
+++ b/src/SerializedTypes.cpp
@@ -14,6 +14,7 @@
#include "TransactionErr.h"
SETUP_LOG();
+DECLARE_INSTANCE(SerializedValue);
STAmount saZero(CURRENCY_ONE, ACCOUNT_ONE, 0);
STAmount saOne(CURRENCY_ONE, ACCOUNT_ONE, 1);
@@ -539,7 +540,6 @@ void STPathSet::add(Serializer& s) const
if (!bFirst)
{
s.add8(STPathElement::typeBoundary);
- bFirst = false;
}
BOOST_FOREACH(const STPathElement& speElement, spPath)
@@ -557,6 +557,8 @@ void STPathSet::add(Serializer& s) const
if (iType & STPathElement::typeIssuer)
s.add160(speElement.getIssuerID());
}
+
+ bFirst = false;
}
s.add8(STPathElement::typeEnd);
}
diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h
index 62f7347c8..4832b4621 100644
--- a/src/SerializedTypes.h
+++ b/src/SerializedTypes.h
@@ -9,7 +9,7 @@
#include "uint256.h"
#include "Serializer.h"
#include "FieldNames.h"
-
+#include "InstanceCounter.h"
enum PathFlags
{
@@ -30,7 +30,9 @@ enum PathFlags
#define ACCOUNT_XNS uint160(0)
#define ACCOUNT_ONE uint160(1) // Used as a place holder
-class SerializedType
+DEFINE_INSTANCE(SerializedValue);
+
+class SerializedType : private IS_INSTANCE(SerializedValue)
{
protected:
SField::ptr fName;
diff --git a/src/Suppression.cpp b/src/Suppression.cpp
index 4b7cad571..ad96d4b15 100644
--- a/src/Suppression.cpp
+++ b/src/Suppression.cpp
@@ -1,39 +1,100 @@
+
#include "Suppression.h"
#include
-bool SuppressionTable::addSuppression(const uint160& suppression)
-{
- boost::mutex::scoped_lock sl(mSuppressionMutex);
+DECLARE_INSTANCE(Suppression);
- if (mSuppressionMap.find(suppression) != mSuppressionMap.end())
- return false;
+Suppression& SuppressionTable::findCreateEntry(const uint256& index, bool& created)
+{
+ boost::unordered_map::iterator fit = mSuppressionMap.find(index);
+
+ if (fit != mSuppressionMap.end())
+ {
+ created = false;
+ return fit->second;
+ }
+ created = true;
time_t now = time(NULL);
time_t expireTime = now - mHoldTime;
- boost::unordered_map< time_t, std::list >::iterator
- it = mSuppressionTimes.begin(), end = mSuppressionTimes.end();
- while (it != end)
+ // See if any supressions need to be expired
+ std::map< time_t, std::list >::iterator it = mSuppressionTimes.begin();
+ if ((it != mSuppressionTimes.end()) && (it->first <= expireTime))
{
- if (it->first <= expireTime)
- {
- BOOST_FOREACH(const uint160& lit, it->second)
- mSuppressionMap.erase(lit);
- it = mSuppressionTimes.erase(it);
- }
- else ++it;
+ BOOST_FOREACH(const uint256& lit, it->second)
+ mSuppressionMap.erase(lit);
+ mSuppressionTimes.erase(it);
}
- mSuppressionMap[suppression] = now;
- mSuppressionTimes[now].push_back(suppression);
+ mSuppressionTimes[now].push_back(index);
+ return mSuppressionMap.insert(std::make_pair(index, Suppression())).first->second;
+}
+bool SuppressionTable::addSuppression(const uint256& index)
+{
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ findCreateEntry(index, created);
+ return created;
+}
+
+Suppression SuppressionTable::getEntry(const uint256& index)
+{
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ return findCreateEntry(index, created);
+}
+
+bool SuppressionTable::addSuppressionPeer(const uint256& index, uint64 peer)
+{
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ findCreateEntry(index, created).addPeer(peer);
+ return created;
+}
+
+bool SuppressionTable::addSuppressionFlags(const uint256& index, int flag)
+{
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ findCreateEntry(index, created).setFlag(flag);
+ return created;
+}
+
+bool SuppressionTable::setFlag(const uint256& index, int flag)
+{ // return: true = changed, false = unchanged
+ assert(flag != 0);
+
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ Suppression &s = findCreateEntry(index, created);
+
+ if ((s.getFlags() & flag) == flag)
+ return false;
+
+ s.setFlag(flag);
return true;
}
-bool SuppressionTable::addSuppression(const uint256& suppression)
+bool SuppressionTable::swapSet(const uint256& index, std::set& peers, int flag)
{
- uint160 u;
- memcpy(u.begin(), suppression.begin() + (suppression.size() - u.size()), u.size());
- return addSuppression(u);
-}
+ boost::mutex::scoped_lock sl(mSuppressionMutex);
+
+ bool created;
+ Suppression &s = findCreateEntry(index, created);
+
+ if ((s.getFlags() & flag) == flag)
+ return false;
+
+ s.swapSet(peers);
+ s.setFlag(flag);
+
+ return true;
+}
\ No newline at end of file
diff --git a/src/Suppression.h b/src/Suppression.h
index 608a57d73..14b611ede 100644
--- a/src/Suppression.h
+++ b/src/Suppression.h
@@ -1,14 +1,43 @@
#ifndef __SUPPRESSION__
#define __SUPPRESSION__
+#include
+#include