mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -12,8 +12,10 @@
|
||||
#include "BitcoinUtil.h"
|
||||
#include "key.h"
|
||||
#include "utils.h"
|
||||
#include "TaggedCache.h"
|
||||
|
||||
Application* theApp=NULL;
|
||||
|
||||
Application* theApp = NULL;
|
||||
|
||||
DatabaseCon::DatabaseCon(const std::string& name, const char *initStrings[], int initCount)
|
||||
{
|
||||
@@ -32,11 +34,12 @@ DatabaseCon::~DatabaseCon()
|
||||
|
||||
Application::Application() :
|
||||
mUNL(mIOService),
|
||||
mNetOps(mIOService, &mMasterLedger),
|
||||
mNetOps(mIOService, &mMasterLedger), mNodeCache(16384, 600),
|
||||
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
|
||||
{
|
||||
RAND_bytes(mNonce256.begin(), mNonce256.size());
|
||||
RAND_bytes(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
|
||||
}
|
||||
|
||||
extern const char *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __APPLICATION__
|
||||
#define __APPLICATION__
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "LedgerMaster.h"
|
||||
#include "UniqueNodeList.h"
|
||||
#include "ConnectionPool.h"
|
||||
@@ -10,12 +12,13 @@
|
||||
#include "Wallet.h"
|
||||
#include "Peer.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "../database/database.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
class RPCDoor;
|
||||
class PeerDoor;
|
||||
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
|
||||
|
||||
class DatabaseCon
|
||||
{
|
||||
@@ -40,6 +43,7 @@ class Application
|
||||
LedgerAcquireMaster mMasterLedgerAcquire;
|
||||
TransactionMaster mMasterTransaction;
|
||||
NetworkOPs mNetOps;
|
||||
NodeCache mNodeCache;
|
||||
|
||||
DatabaseCon* mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
|
||||
|
||||
@@ -48,6 +52,7 @@ class Application
|
||||
RPCDoor* mRPCDoor;
|
||||
|
||||
uint256 mNonce256;
|
||||
std::size_t mNonceST;
|
||||
|
||||
std::map<std::string, Peer::pointer> mPeerMap;
|
||||
boost::recursive_mutex mPeerMapLock;
|
||||
@@ -56,26 +61,28 @@ public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
ConnectionPool& getConnectionPool() { return mConnectionPool; }
|
||||
ConnectionPool& getConnectionPool() { return mConnectionPool; }
|
||||
|
||||
UniqueNodeList& getUNL() { return mUNL; }
|
||||
UniqueNodeList& getUNL() { return mUNL; }
|
||||
|
||||
Wallet& getWallet() { return mWallet ; }
|
||||
NetworkOPs& getOPs() { return mNetOps; }
|
||||
Wallet& getWallet() { return mWallet ; }
|
||||
NetworkOPs& getOPs() { return mNetOps; }
|
||||
|
||||
boost::asio::io_service& getIOService() { return mIOService; }
|
||||
boost::asio::io_service& getIOService() { return mIOService; }
|
||||
|
||||
LedgerMaster& getMasterLedger() { return mMasterLedger; }
|
||||
LedgerAcquireMaster& getMasterLedgerAcquire() { return mMasterLedgerAcquire; }
|
||||
TransactionMaster& getMasterTransaction() { return mMasterTransaction; }
|
||||
LedgerMaster& getMasterLedger() { return mMasterLedger; }
|
||||
LedgerAcquireMaster& getMasterLedgerAcquire() { return mMasterLedgerAcquire; }
|
||||
TransactionMaster& getMasterTransaction() { return mMasterTransaction; }
|
||||
NodeCache& getNodeCache() { return mNodeCache; }
|
||||
|
||||
DatabaseCon* getTxnDB() { return mTxnDB; }
|
||||
DatabaseCon* getLedgerDB() { return mLedgerDB; }
|
||||
DatabaseCon* getWalletDB() { return mWalletDB; }
|
||||
DatabaseCon* getHashNodeDB() { return mHashNodeDB; }
|
||||
DatabaseCon* getNetNodeDB() { return mNetNodeDB; }
|
||||
DatabaseCon* getTxnDB() { return mTxnDB; }
|
||||
DatabaseCon* getLedgerDB() { return mLedgerDB; }
|
||||
DatabaseCon* getWalletDB() { return mWalletDB; }
|
||||
DatabaseCon* getHashNodeDB() { return mHashNodeDB; }
|
||||
DatabaseCon* getNetNodeDB() { return mNetNodeDB; }
|
||||
|
||||
uint256 getNonce256() { return mNonce256; }
|
||||
uint256 getNonce256() { return mNonce256; }
|
||||
std::size_t getNonceST() { return mNonceST; }
|
||||
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
@@ -67,7 +67,7 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
|
||||
}
|
||||
|
||||
LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE_TIMEOUT),
|
||||
mHaveBase(false), mHaveState(false), mHaveTransactions(false)
|
||||
mFilter(&theApp->getNodeCache()), mHaveBase(false), mHaveState(false), mHaveTransactions(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Acquiring ledger " << mHash.GetHex() << std::endl;
|
||||
@@ -152,7 +152,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
{
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::vector<uint256> nodeHashes;
|
||||
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
||||
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128, &mFilter);
|
||||
if (nodeIDs.empty())
|
||||
{
|
||||
if (!mLedger->peekTransactionMap()->isValid()) mFailed = true;
|
||||
@@ -204,7 +204,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
{
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::vector<uint256> nodeHashes;
|
||||
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
||||
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128, &mFilter);
|
||||
if (nodeIDs.empty())
|
||||
{
|
||||
if (!mLedger->peekAccountStateMap()->isValid()) mFailed = true;
|
||||
@@ -303,7 +303,7 @@ bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait))
|
||||
return false;
|
||||
}
|
||||
else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
||||
else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
|
||||
return false;
|
||||
++nodeIDit;
|
||||
++nodeDatait;
|
||||
@@ -333,7 +333,7 @@ bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), *nodeDatait))
|
||||
return false;
|
||||
}
|
||||
else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
||||
else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
|
||||
return false;
|
||||
++nodeIDit;
|
||||
++nodeDatait;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "Ledger.h"
|
||||
#include "Peer.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "../obj/src/newcoin.pb.h"
|
||||
|
||||
class PeerSet
|
||||
@@ -53,6 +54,31 @@ private:
|
||||
static void TimerEntry(boost::weak_ptr<PeerSet>, const boost::system::error_code& result);
|
||||
};
|
||||
|
||||
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
|
||||
typedef std::vector<unsigned char> VUC;
|
||||
|
||||
class THSyncFilter : public SHAMapSyncFilter
|
||||
{
|
||||
protected:
|
||||
NodeCache* mCache;
|
||||
|
||||
public:
|
||||
THSyncFilter(NodeCache* cache) : mCache(cache) { ; }
|
||||
virtual void gotNode(const SHAMapNode& id, const uint256& nodeHash,
|
||||
const std::vector<unsigned char>& nodeData, bool)
|
||||
{
|
||||
boost::shared_ptr<VUC> ptr = boost::make_shared<VUC>(nodeData);
|
||||
mCache->canonicalize(nodeHash, ptr);
|
||||
}
|
||||
virtual bool haveNode(const SHAMapNode& id, const uint256& nodeHash, std::vector<unsigned char>& nodeData)
|
||||
{
|
||||
boost::shared_ptr<VUC> entry = mCache->fetch(nodeHash);
|
||||
if (!entry) return false;
|
||||
nodeData = *entry;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LedgerAcquire : public PeerSet, public boost::enable_shared_from_this<LedgerAcquire>
|
||||
{ // A ledger we are trying to acquire
|
||||
public:
|
||||
@@ -60,6 +86,7 @@ public:
|
||||
|
||||
protected:
|
||||
Ledger::pointer mLedger;
|
||||
THSyncFilter mFilter;
|
||||
bool mHaveBase, mHaveState, mHaveTransactions;
|
||||
|
||||
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
|
||||
@@ -106,4 +133,5 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
#define TRUST_NETWORK
|
||||
|
||||
TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false)
|
||||
TransactionAcquire::TransactionAcquire(const uint256& hash)
|
||||
: PeerSet(hash, 1), mFilter(&theApp->getNodeCache()), mHaveRoot(false)
|
||||
{
|
||||
mMap = boost::make_shared<SHAMap>();
|
||||
mMap->setSynching();
|
||||
@@ -48,7 +49,7 @@ void TransactionAcquire::trigger(Peer::pointer peer)
|
||||
Log(lsTRACE) << "Have root";
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::vector<uint256> nodeHashes;
|
||||
mMap->getMissingNodes(nodeIDs, nodeHashes, 256);
|
||||
mMap->getMissingNodes(nodeIDs, nodeHashes, 256, &mFilter);
|
||||
if (nodeIDs.empty())
|
||||
{
|
||||
if (mMap->isValid())
|
||||
@@ -100,7 +101,7 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
|
||||
return false;
|
||||
else mHaveRoot = true;
|
||||
}
|
||||
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait))
|
||||
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
|
||||
return false;
|
||||
++nodeIDit;
|
||||
++nodeDatait;
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
|
||||
protected:
|
||||
SHAMap::pointer mMap;
|
||||
THSyncFilter mFilter; // FIXME: Should use transaction master too
|
||||
bool mHaveRoot;
|
||||
|
||||
void onTimer() { trigger(Peer::pointer()); }
|
||||
@@ -47,7 +48,7 @@ protected:
|
||||
int mYays, mNays;
|
||||
bool mOurPosition;
|
||||
std::vector<unsigned char> transaction;
|
||||
boost::unordered_map<uint256, bool, hash_SMN> mVotes;
|
||||
boost::unordered_map<uint256, bool> mVotes;
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<LCTransaction> pointer;
|
||||
@@ -85,17 +86,17 @@ protected:
|
||||
LedgerProposal::pointer mOurPosition;
|
||||
|
||||
// Convergence tracking, trusted peers indexed by hash of public key
|
||||
boost::unordered_map<uint256, LedgerProposal::pointer, hash_SMN> mPeerPositions;
|
||||
boost::unordered_map<uint256, LedgerProposal::pointer> mPeerPositions;
|
||||
|
||||
// Transaction Sets, indexed by hash of transaction tree
|
||||
boost::unordered_map<uint256, SHAMap::pointer, hash_SMN> mComplete;
|
||||
boost::unordered_map<uint256, TransactionAcquire::pointer, hash_SMN> mAcquiring;
|
||||
boost::unordered_map<uint256, SHAMap::pointer> mComplete;
|
||||
boost::unordered_map<uint256, TransactionAcquire::pointer> mAcquiring;
|
||||
|
||||
// Peer sets
|
||||
boost::unordered_map<uint256, std::vector< boost::weak_ptr<Peer> >, hash_SMN> mPeerData;
|
||||
boost::unordered_map<uint256, std::vector< boost::weak_ptr<Peer> > > mPeerData;
|
||||
|
||||
// Disputed transactions
|
||||
boost::unordered_map<uint256, LCTransaction::pointer, hash_SMN> mDisputes;
|
||||
boost::unordered_map<uint256, LCTransaction::pointer> mDisputes;
|
||||
|
||||
// final accept logic
|
||||
static void Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::pointer txSet);
|
||||
|
||||
@@ -285,7 +285,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
// Do we have sufficient validations for our last closed ledger? Or do sufficient nodes
|
||||
// agree? And do we have no better ledger available?
|
||||
// If so, we are either tracking or full.
|
||||
boost::unordered_map<uint256, ValidationCount, hash_SMN> ledgers;
|
||||
boost::unordered_map<uint256, ValidationCount> ledgers;
|
||||
|
||||
for (std::vector<Peer::pointer>::iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
|
||||
{
|
||||
|
||||
@@ -726,6 +726,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
{
|
||||
SHAMap::pointer map;
|
||||
newcoin::TMLedgerData reply;
|
||||
bool fatLeaves = true;
|
||||
|
||||
if (packet.itype() == newcoin::liTS_CANDIDATE)
|
||||
{ // Request is for a transaction candidate set
|
||||
@@ -748,6 +749,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
reply.set_ledgerseq(0);
|
||||
reply.set_ledgerhash(txHash.begin(), txHash.size());
|
||||
reply.set_type(newcoin::liTS_CANDIDATE);
|
||||
fatLeaves = false; // We'll already have most transactions
|
||||
}
|
||||
else
|
||||
{ // Figure out what ledger they want
|
||||
@@ -828,7 +830,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
}
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::list< std::vector<unsigned char> > rawNodes;
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes))
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes, fatLeaves))
|
||||
{
|
||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||
std::list< std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
#include "SHAMap.h"
|
||||
#include "Application.h"
|
||||
|
||||
std::size_t hash_SMN::operator() (const SHAMapNode& mn) const
|
||||
std::size_t hash_value(const SHAMapNode& mn)
|
||||
{
|
||||
return mn.getDepth()
|
||||
^ *reinterpret_cast<const std::size_t *>(mn.getNodeID().begin())
|
||||
^ *reinterpret_cast<const std::size_t *>(theApp->getNonce256().begin());
|
||||
std::size_t seed = theApp->getNonceST();
|
||||
boost::hash_combine(seed, mn.getDepth());
|
||||
return mn.getNodeID().hash_combine(seed);
|
||||
}
|
||||
|
||||
std::size_t hash_SMN::operator() (const uint256& u) const
|
||||
std::size_t hash_value(const uint256& u)
|
||||
{
|
||||
return *reinterpret_cast<const std::size_t *>(u.begin())
|
||||
^ *reinterpret_cast<const std::size_t *>(theApp->getNonce256().begin());
|
||||
std::size_t seed = theApp->getNonceST();
|
||||
return u.hash_combine(seed);
|
||||
}
|
||||
|
||||
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
|
||||
@@ -671,7 +671,7 @@ void SHAMap::dump(bool hash)
|
||||
|
||||
std::cerr << " MAP Contains" << std::endl;
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
for(boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer, hash_SMN>::iterator it = mTNByID.begin();
|
||||
for(boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it = mTNByID.begin();
|
||||
it != mTNByID.end(); ++it)
|
||||
{
|
||||
std::cerr << it->second->getString() << std::endl;
|
||||
|
||||
32
src/SHAMap.h
32
src/SHAMap.h
@@ -76,14 +76,8 @@ public:
|
||||
SHAMapNode(const void *ptr, int len);
|
||||
};
|
||||
|
||||
class hash_SMN
|
||||
{
|
||||
|
||||
public:
|
||||
std::size_t operator() (const SHAMapNode& mn) const;
|
||||
|
||||
std::size_t operator() (const uint256& u) const;
|
||||
};
|
||||
extern std::size_t hash_value(const SHAMapNode& mn);
|
||||
extern std::size_t hash_value(const uint256& u);
|
||||
|
||||
class SHAMapItem
|
||||
{ // an item stored in a SHAMap
|
||||
@@ -225,6 +219,18 @@ enum SHAMapState
|
||||
Invalid = 4, // Map is known not to be valid (usually synching a corrupt ledger)
|
||||
};
|
||||
|
||||
class SHAMapSyncFilter
|
||||
{
|
||||
public:
|
||||
SHAMapSyncFilter() { ; }
|
||||
virtual ~SHAMapSyncFilter() { ; }
|
||||
virtual void gotNode(const SHAMapNode& id, const uint256& nodeHash,
|
||||
const std::vector<unsigned char>& nodeData, bool isLeaf)
|
||||
{ ; }
|
||||
virtual bool haveNode(const SHAMapNode& id, const uint256& nodeHash, std::vector<unsigned char>& nodeData)
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
class SHAMap
|
||||
{
|
||||
public:
|
||||
@@ -234,7 +240,7 @@ public:
|
||||
private:
|
||||
uint32 mSeq;
|
||||
mutable boost::recursive_mutex mLock;
|
||||
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer, hash_SMN> mTNByID;
|
||||
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer> mTNByID;
|
||||
|
||||
boost::shared_ptr<std::map<SHAMapNode, SHAMapTreeNode::pointer> > mDirtyNodes;
|
||||
|
||||
@@ -299,12 +305,14 @@ public:
|
||||
SHAMapItem::pointer peekPrevItem(const uint256&);
|
||||
|
||||
// comparison/sync functions
|
||||
void getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max);
|
||||
void getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
|
||||
SHAMapSyncFilter* filter);
|
||||
bool getNodeFat(const SHAMapNode& node, std::vector<SHAMapNode>& nodeIDs,
|
||||
std::list<std::vector<unsigned char> >& rawNode);
|
||||
std::list<std::vector<unsigned char> >& rawNode, bool fatLeaves);
|
||||
bool addRootNode(const uint256& hash, const std::vector<unsigned char>& rootNode);
|
||||
bool addRootNode(const std::vector<unsigned char>& rootNode);
|
||||
bool addKnownNode(const SHAMapNode& nodeID, const std::vector<unsigned char>& rawNode);
|
||||
bool addKnownNode(const SHAMapNode& nodeID, const std::vector<unsigned char>& rawNode,
|
||||
SHAMapSyncFilter* filter);
|
||||
|
||||
// status functions
|
||||
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
|
||||
|
||||
@@ -11,19 +11,20 @@
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max)
|
||||
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
|
||||
SHAMapSyncFilter* filter)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
assert(root->isValid());
|
||||
|
||||
if(root->isFullBelow())
|
||||
if (root->isFullBelow())
|
||||
{
|
||||
clearSynching();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!root->isInner())
|
||||
if (!root->isInner())
|
||||
{
|
||||
Log(lsWARNING) << "synching empty tree";
|
||||
return;
|
||||
@@ -43,7 +44,27 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
int branch = (base + ii) % 16;
|
||||
if (!node->isEmptyBranch(branch))
|
||||
{
|
||||
SHAMapTreeNode::pointer d = getNode(node->getChildNodeID(branch), node->getChildHash(branch), false);
|
||||
SHAMapNode childID = node->getChildNodeID(branch);
|
||||
const uint256& childHash = node->getChildHash(branch);
|
||||
SHAMapTreeNode::pointer d = getNode(childID, childHash, false);
|
||||
if ((!d) && (filter != NULL))
|
||||
{
|
||||
std::vector<unsigned char> nodeData;
|
||||
if (filter->haveNode(childID, childHash, nodeData))
|
||||
{
|
||||
d = boost::make_shared<SHAMapTreeNode>(childID, nodeData, mSeq);
|
||||
if (childHash != d->getNodeHash())
|
||||
{
|
||||
Log(lsERROR) << "Wrong hash from cached object";
|
||||
d = SHAMapTreeNode::pointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "Got sync node from cache";
|
||||
mTNByID[*d] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!d)
|
||||
{
|
||||
nodeIDs.push_back(node->getChildNodeID(branch));
|
||||
@@ -58,14 +79,14 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
}
|
||||
|
||||
bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector<SHAMapNode>& nodeIDs,
|
||||
std::list<std::vector<unsigned char> >& rawNodes)
|
||||
std::list<std::vector<unsigned char> >& rawNodes, bool fatLeaves)
|
||||
{ // Gets a node and some of its children
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
SHAMapTreeNode::pointer node = getNode(wanted);
|
||||
if (!node)
|
||||
{
|
||||
assert(false); // Remove for release, this can happen if we get a bogus request
|
||||
assert(false); // FIXME Remove for release, this can happen if we get a bogus request
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,7 +103,7 @@ bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector<SHAMapNode>& nodeI
|
||||
{
|
||||
SHAMapTreeNode::pointer nextNode = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||
assert(nextNode);
|
||||
if(nextNode)
|
||||
if (nextNode && (fatLeaves || !nextNode->isLeaf()))
|
||||
{
|
||||
nodeIDs.push_back(*nextNode);
|
||||
Serializer s;
|
||||
@@ -153,7 +174,8 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector<unsigned char>&
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned char>& rawNode)
|
||||
bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned char>& rawNode,
|
||||
SHAMapSyncFilter* filter)
|
||||
{ // return value: true=okay, false=error
|
||||
assert(!node.isRoot());
|
||||
if (!isSynching()) return false;
|
||||
@@ -199,6 +221,8 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
||||
if (hash != newNode->getNodeHash()) // these aren't the droids we're looking for
|
||||
return false;
|
||||
|
||||
if (filter) filter->gotNode(node, hash, rawNode, newNode->isLeaf());
|
||||
|
||||
mTNByID[*newNode] = newNode;
|
||||
if (!newNode->isLeaf())
|
||||
return true; // only a leaf can fill a branch
|
||||
@@ -209,7 +233,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
||||
iNode = stack.top();
|
||||
stack.pop();
|
||||
assert(iNode->isInner());
|
||||
for(int i = 0; i < 16; ++i)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (!iNode->isEmptyBranch(i))
|
||||
{
|
||||
SHAMapTreeNode::pointer nextNode = getNode(iNode->getChildNodeID(i), iNode->getChildHash(i), false);
|
||||
@@ -234,7 +258,7 @@ bool SHAMap::deepCompare(SHAMap& other)
|
||||
stack.pop();
|
||||
|
||||
SHAMapTreeNode::pointer otherNode;
|
||||
if(node->isRoot()) otherNode = other.root;
|
||||
if (node->isRoot()) otherNode = other.root;
|
||||
else otherNode = other.getNode(*node, node->getNodeHash(), false);
|
||||
|
||||
if (!otherNode)
|
||||
@@ -262,11 +286,11 @@ bool SHAMap::deepCompare(SHAMap& other)
|
||||
{
|
||||
if (!otherNode->isInner())
|
||||
return false;
|
||||
for(int i=0; i<16; i++)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
if(node->isEmptyBranch(i))
|
||||
if (node->isEmptyBranch(i))
|
||||
{
|
||||
if(!otherNode->isEmptyBranch(i)) return false;
|
||||
if (!otherNode->isEmptyBranch(i)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -290,9 +314,9 @@ bool SHAMap::deepCompare(SHAMap& other)
|
||||
|
||||
static SHAMapItem::pointer makeRandomAS()
|
||||
{
|
||||
Serializer s;
|
||||
for(int d = 0; d < 3; ++d) s.add32(rand());
|
||||
return boost::make_shared<SHAMapItem>(s.getRIPEMD160().to256(), s.peekData());
|
||||
Serializer s;
|
||||
for (int d = 0; d < 3; ++d) s.add32(rand());
|
||||
return boost::make_shared<SHAMapItem>(s.getRIPEMD160().to256(), s.peekData());
|
||||
}
|
||||
|
||||
static bool confuseMap(SHAMap &map, int count)
|
||||
@@ -362,32 +386,31 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
|
||||
SHAMap source, destination;
|
||||
|
||||
|
||||
// add random data to the source map
|
||||
int items = 10000;
|
||||
for (int i = 0; i < items; ++i)
|
||||
source.addItem(*makeRandomAS(), false);
|
||||
|
||||
Log(lsTRACE) << "Adding items, then removing them";
|
||||
if(!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");
|
||||
if (!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");
|
||||
|
||||
source.setImmutable();
|
||||
|
||||
Log(lsTRACE) << "SOURCE COMPLETE, SYNCHING";
|
||||
|
||||
std::vector<SHAMapNode> nodeIDs, gotNodeIDs;
|
||||
std::list<std::vector<unsigned char> > gotNodes;
|
||||
std::list< std::vector<unsigned char> > gotNodes;
|
||||
std::vector<uint256> hashes;
|
||||
|
||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||
std::list<std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
std::list< std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
|
||||
int passes = 0;
|
||||
int nodes = 0;
|
||||
|
||||
destination.setSynching();
|
||||
|
||||
if (!source.getNodeFat(SHAMapNode(), nodeIDs, gotNodes))
|
||||
if (!source.getNodeFat(SHAMapNode(), nodeIDs, gotNodes, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat(root) fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
@@ -416,14 +439,14 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
hashes.clear();
|
||||
|
||||
// get the list of nodes we know we need
|
||||
destination.getMissingNodes(nodeIDs, hashes, 2048);
|
||||
if(nodeIDs.empty()) break;
|
||||
destination.getMissingNodes(nodeIDs, hashes, 2048, NULL);
|
||||
if (nodeIDs.empty()) break;
|
||||
|
||||
Log(lsINFO) << nodeIDs.size() << " needed nodes";
|
||||
|
||||
// get as many nodes as possible based on this information
|
||||
for (nodeIDIterator = nodeIDs.begin(); nodeIDIterator != nodeIDs.end(); ++nodeIDIterator)
|
||||
if (!source.getNodeFat(*nodeIDIterator, gotNodeIDs, gotNodes))
|
||||
if (!source.getNodeFat(*nodeIDIterator, gotNodeIDs, gotNodes, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
@@ -446,7 +469,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
#ifdef SMS_DEBUG
|
||||
bytes += rawNodeIterator->size();
|
||||
#endif
|
||||
if (!destination.addKnownNode(*nodeIDIterator, *rawNodeIterator))
|
||||
if (!destination.addKnownNode(*nodeIDIterator, *rawNodeIterator, NULL))
|
||||
{
|
||||
Log(lsTRACE) << "AddKnownNode fails";
|
||||
BOOST_FAIL("AddKnownNode");
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <map>
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// This class implemented a cache and a map. The cache keeps objects alive
|
||||
@@ -25,10 +26,10 @@ protected:
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
int mTargetSize, mTargetAge;
|
||||
std::map<key_type, cache_entry> mCache; // Hold strong reference to recent objects
|
||||
boost::unordered_map<key_type, cache_entry> mCache; // Hold strong reference to recent objects
|
||||
time_t mLastSweep;
|
||||
|
||||
std::map<key_type, weak_data_ptr> mMap; // Track stored objects
|
||||
boost::unordered_map<key_type, weak_data_ptr> mMap; // Track stored objects
|
||||
|
||||
public:
|
||||
TaggedCache(int size, int age) : mTargetSize(size), mTargetAge(age), mLastSweep(time(NULL)) { ; }
|
||||
@@ -81,7 +82,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
time_t target = now - mTargetAge;
|
||||
|
||||
// Pass 1, remove old objects from cache
|
||||
typename std::map<key_type, cache_entry>::iterator cit = mCache.begin();
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (cit->second->second.first < target)
|
||||
@@ -90,7 +91,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
}
|
||||
|
||||
// Pass 2, remove dead objects from map
|
||||
typename std::map<key_type, weak_data_ptr>::iterator mit = mMap.begin();
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.begin();
|
||||
while (mit != mMap.end())
|
||||
{
|
||||
if (mit->second->expired())
|
||||
@@ -104,7 +105,7 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
// Is the object in the map?
|
||||
typename std::map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) return false;
|
||||
if (mit->second->expired())
|
||||
{ // in map, but expired
|
||||
@@ -113,7 +114,7 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch
|
||||
}
|
||||
|
||||
// Is the object in the cache?
|
||||
typename std::map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
{ // in both map and cache
|
||||
cit->second->first = time(NULL);
|
||||
@@ -129,7 +130,7 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(c
|
||||
{ // Remove from cache, map unaffected
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
typename std::map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end()) return false;
|
||||
mCache.erase(cit);
|
||||
return true;
|
||||
@@ -141,7 +142,7 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
// Return values: true=we had the data already
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
typename std::map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end())
|
||||
{ // not in map
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||
@@ -159,7 +160,7 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
assert(!!data);
|
||||
|
||||
// Valid in map, is it in cache?
|
||||
typename std::map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
cit->second.first = time(NULL); // Yes, refesh
|
||||
else // no, add to cache
|
||||
@@ -174,7 +175,7 @@ boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
// Is it in the map?
|
||||
typename std::map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) return data_ptr(); // No, we're done
|
||||
if (mit->second.expired())
|
||||
{ // in map, but expired
|
||||
@@ -185,7 +186,7 @@ boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
boost::shared_ptr<c_Data> data = mit->second.lock();
|
||||
|
||||
// Valid in map, is it in the cache?
|
||||
typename std::map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
cit->second.first = time(NULL); // Yes, refresh
|
||||
else // No, add to cache
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "BitcoinUtil.h"
|
||||
#include "Serializer.h"
|
||||
#include "SerializedTransaction.h"
|
||||
#include "Log.h"
|
||||
|
||||
Transaction::Transaction(const SerializedTransaction::pointer sit, bool bValidate)
|
||||
: mInLedger(0), mStatus(INVALID), mTransaction(sit)
|
||||
@@ -43,6 +44,7 @@ Transaction::pointer Transaction::sharedTransaction(const std::vector<unsigned c
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << "Exception constructing transaction";
|
||||
return boost::shared_ptr<Transaction>();
|
||||
}
|
||||
}
|
||||
@@ -66,8 +68,8 @@ Transaction::Transaction(
|
||||
|
||||
mTransaction = boost::make_shared<SerializedTransaction>(ttKind);
|
||||
|
||||
std::cerr << str(boost::format("Transaction: account: %s") % naSourceAccount.humanAccountID()) << std::endl;
|
||||
std::cerr << str(boost::format("Transaction: mAccountFrom: %s") % mAccountFrom.humanAccountID()) << std::endl;
|
||||
Log(lsINFO) << str(boost::format("Transaction: account: %s") % naSourceAccount.humanAccountID());
|
||||
Log(lsINFO) << str(boost::format("Transaction: mAccountFrom: %s") % mAccountFrom.humanAccountID());
|
||||
mTransaction->setSigningPubKey(mFromPubKey);
|
||||
mTransaction->setSourceAccount(mAccountFrom);
|
||||
mTransaction->setSequence(uSeq);
|
||||
@@ -86,16 +88,12 @@ bool Transaction::sign(const NewcoinAddress& naAccountPrivate)
|
||||
|
||||
if (!naAccountPrivate.isValid())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "No private key for signing" << std::endl;
|
||||
#endif
|
||||
Log(lsWARNING) << "No private key for signing";
|
||||
bResult = false;
|
||||
}
|
||||
else if (!getSTransaction()->sign(naAccountPrivate))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Failed to make signature" << std::endl;
|
||||
#endif
|
||||
Log(lsWARNING) << "Failed to make signature";
|
||||
assert(false);
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
std::cerr << "applyTransaction>" << std::endl;
|
||||
|
||||
mLedger = mDefaultLedger;
|
||||
assert(mLedger);
|
||||
if (mAlternateLedger && (targetLedger != 0) &&
|
||||
(targetLedger != mLedger->getLedgerSeq()) && (targetLedger == mAlternateLedger->getLedgerSeq()))
|
||||
{
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -136,6 +138,13 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::size_t hash_combine(std::size_t& seed) const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; ++i)
|
||||
boost::hash_combine(seed, pn[i]);
|
||||
return seed;
|
||||
}
|
||||
|
||||
friend inline int compare(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
const unsigned char* pA = a.begin();
|
||||
|
||||
Reference in New Issue
Block a user