From c9cb46577614273cd8e0d7f64e61ede47b38d93e Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 14 Nov 2012 16:28:33 -0800 Subject: [PATCH 1/9] . --- newcoin.vcxproj | 1 - newcoin.vcxproj.filters | 3 --- test/config.js | 3 ++- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 32ee35c9e..92e02d4a5 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -145,7 +145,6 @@ - diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 0380497b0..c33506595 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -198,9 +198,6 @@ Source Files - - Source Files - Source Files diff --git a/test/config.js b/test/config.js index 42ce8bea4..425478cef 100644 --- a/test/config.js +++ b/test/config.js @@ -14,12 +14,13 @@ exports.servers = { // A local test server. "alpha" : { 'trusted' : true, + 'no_server' : true, // "peer_ip" : "0.0.0.0", // "peer_port" : 51235, 'rpc_ip' : "0.0.0.0", 'rpc_port' : 5005, 'websocket_ip' : "127.0.0.1", - 'websocket_port' : 6005, + 'websocket_port' : 5006, // 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h", // 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta" } From 89d54999c9c1b28d89fc824e34369c9acd31b101 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 21 Nov 2012 09:28:09 -0800 Subject: [PATCH 2/9] Rework the way the results of ledger and TX map acquisition is passed up and down the call chain so that the peer logic will know how helpful peers are being, not just whether they're sending invalid data. --- src/cpp/ripple/LedgerAcquire.cpp | 67 ++++++++++++++++-------------- src/cpp/ripple/LedgerAcquire.h | 12 +++--- src/cpp/ripple/LedgerConsensus.cpp | 22 +++++----- src/cpp/ripple/LedgerConsensus.h | 5 ++- src/cpp/ripple/NetworkOPs.cpp | 4 +- src/cpp/ripple/NetworkOPs.h | 2 +- src/cpp/ripple/Peer.cpp | 6 ++- src/cpp/ripple/Peer.h | 6 +++ src/cpp/ripple/ProofOfWork.cpp | 20 ++++++++- src/cpp/ripple/SHAMap.h | 44 ++++++++++++++++++-- src/cpp/ripple/SHAMapSync.cpp | 51 ++++++++++++----------- 11 files changed, 155 insertions(+), 84 deletions(-) diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp index 0d979f61d..c3387cf5f 100644 --- a/src/cpp/ripple/LedgerAcquire.cpp +++ b/src/cpp/ripple/LedgerAcquire.cpp @@ -396,7 +396,7 @@ bool LedgerAcquire::takeBase(const std::string& data) } bool LedgerAcquire::takeTxNode(const std::list& nodeIDs, - const std::list< std::vector >& data) + const std::list< std::vector >& data, SMAddNode& san) { if (!mHaveBase) return false; std::list::const_iterator nodeIDit = nodeIDs.begin(); @@ -406,11 +406,15 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs, { if (nodeIDit->isRoot()) { - if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait, snfWIRE, &tFilter)) + if (!san.combine(mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait, + snfWIRE, &tFilter))) + return false; + } + else + { + if (!san.combine(mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter))) return false; } - else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter)) - return false; ++nodeIDit; ++nodeDatait; } @@ -428,7 +432,7 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs, } bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, - const std::list< std::vector >& data) + const std::list< std::vector >& data, SMAddNode& san) { cLog(lsTRACE) << "got ASdata (" << nodeIDs.size() <<") acquiring ledger " << mHash; tLog(nodeIDs.size() == 1, lsTRACE) << "got AS node: " << nodeIDs.front(); @@ -446,14 +450,14 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, { if (nodeIDit->isRoot()) { - if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), - *nodeDatait, snfWIRE, &tFilter)) + if (!san.combine(mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), + *nodeDatait, snfWIRE, &tFilter))) { cLog(lsWARNING) << "Bad ledger base"; return false; } } - else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter)) + else if (!san.combine(mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &tFilter))) { cLog(lsWARNING) << "Unable to add AS node"; return false; @@ -474,24 +478,22 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, return true; } -bool LedgerAcquire::takeAsRootNode(const std::vector& data) +bool LedgerAcquire::takeAsRootNode(const std::vector& data, SMAddNode& san) { if (!mHaveBase) return false; AccountStateSF tFilter(mLedger->getHash(), mLedger->getLedgerSeq()); - if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), data, snfWIRE, &tFilter)) - return false; - return true; + return san.combine( + mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), data, snfWIRE, &tFilter)); } -bool LedgerAcquire::takeTxRootNode(const std::vector& data) +bool LedgerAcquire::takeTxRootNode(const std::vector& data, SMAddNode& san) { if (!mHaveBase) return false; TransactionStateSF tFilter(mLedger->getHash(), mLedger->getLedgerSeq()); - if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), data, snfWIRE, &tFilter)) - return false; - return true; + return san.combine( + mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), data, snfWIRE, &tFilter)); } LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash) @@ -532,13 +534,13 @@ void LedgerAcquireMaster::dropLedger(const uint256& hash) mLedgers.erase(hash); } -bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref peer) +SMAddNode LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref peer) { uint256 hash; if (packet.ledgerhash().size() != 32) { std::cerr << "Acquire error" << std::endl; - return false; + return SMAddNode::invalid(); } memcpy(hash.begin(), packet.ledgerhash().data(), 32); cLog(lsTRACE) << "Got data (" << packet.nodes().size() << ") for acquiring ledger: " << hash; @@ -547,7 +549,7 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref if (!ledger) { cLog(lsINFO) << "Got data for ledger we're not acquiring"; - return false; + return SMAddNode(); } if (packet.type() == ripple::liBASE) @@ -555,23 +557,24 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref if (packet.nodes_size() < 1) { cLog(lsWARNING) << "Got empty base data"; - return false; + return SMAddNode::invalid(); } if (!ledger->takeBase(packet.nodes(0).nodedata())) { cLog(lsWARNING) << "Got invalid base data"; - return false; + return SMAddNode::invalid(); } - if ((packet.nodes().size() > 1) && !ledger->takeAsRootNode(strCopy(packet.nodes(1).nodedata()))) + SMAddNode san = SMAddNode::useful(); + if ((packet.nodes().size() > 1) && !ledger->takeAsRootNode(strCopy(packet.nodes(1).nodedata()), san)) { cLog(lsWARNING) << "Included ASbase invalid"; } - if ((packet.nodes().size() > 2) && !ledger->takeTxRootNode(strCopy(packet.nodes(2).nodedata()))) + if ((packet.nodes().size() > 2) && !ledger->takeTxRootNode(strCopy(packet.nodes(2).nodedata()), san)) { cLog(lsWARNING) << "Included TXbase invalid"; } ledger->trigger(peer, false); - return true; + return san; } if ((packet.type() == ripple::liTX_NODE) || (packet.type() == ripple::liAS_NODE)) @@ -581,8 +584,8 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref if (packet.nodes().size() <= 0) { - cLog(lsINFO) << "Got request for no nodes"; - return false; + cLog(lsINFO) << "Got response with no nodes"; + return SMAddNode::invalid(); } for (int i = 0; i < packet.nodes().size(); ++i) { @@ -590,24 +593,24 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref if (!node.has_nodeid() || !node.has_nodedata()) { cLog(lsWARNING) << "Got bad node"; - return false; + return SMAddNode::invalid(); } nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size())); nodeData.push_back(std::vector(node.nodedata().begin(), node.nodedata().end())); } - bool ret; + SMAddNode ret; if (packet.type() == ripple::liTX_NODE) - ret = ledger->takeTxNode(nodeIDs, nodeData); + ledger->takeTxNode(nodeIDs, nodeData, ret); else - ret = ledger->takeAsNode(nodeIDs, nodeData); - if (ret) + ledger->takeAsNode(nodeIDs, nodeData, ret); + if (!ret.isInvalid()) ledger->trigger(peer, false); return ret; } cLog(lsWARNING) << "Not sure what ledger data we got"; - return false; + return SMAddNode::invalid(); } // vim:ts=4 diff --git a/src/cpp/ripple/LedgerAcquire.h b/src/cpp/ripple/LedgerAcquire.h index eab3e47d8..2f9778c56 100644 --- a/src/cpp/ripple/LedgerAcquire.h +++ b/src/cpp/ripple/LedgerAcquire.h @@ -97,10 +97,12 @@ public: void addOnComplete(boost::function); bool takeBase(const std::string& data); - bool takeTxNode(const std::list& IDs, const std::list >& data); - bool takeTxRootNode(const std::vector& data); - bool takeAsNode(const std::list& IDs, const std::list >& data); - bool takeAsRootNode(const std::vector& data); + bool takeTxNode(const std::list& IDs, const std::list >& data, + SMAddNode&); + bool takeTxRootNode(const std::vector& data, SMAddNode&); + bool takeAsNode(const std::list& IDs, const std::list >& data, + SMAddNode&); + bool takeAsRootNode(const std::vector& data, SMAddNode&); void trigger(Peer::ref, bool timer); bool tryLocal(); void addPeers(); @@ -119,7 +121,7 @@ public: LedgerAcquire::pointer find(const uint256& hash); bool hasLedger(const uint256& ledgerHash); void dropLedger(const uint256& ledgerHash); - bool gotLedgerData(ripple::TMLedgerData& packet, Peer::ref); + SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref); }; #endif diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 7cc01870d..27ac245ae 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -126,21 +126,23 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer) resetTimer(); } -bool TransactionAcquire::takeNodes(const std::list& nodeIDs, +SMAddNode TransactionAcquire::takeNodes(const std::list& nodeIDs, const std::list< std::vector >& data, Peer::ref peer) { if (mComplete) { cLog(lsTRACE) << "TX set complete"; - return true; + return SMAddNode(); } if (mFailed) { cLog(lsTRACE) << "TX set failed"; - return false; + return SMAddNode(); } try { + if (nodeIDs.empty()) + return SMAddNode::invalid(); std::list::const_iterator nodeIDit = nodeIDs.begin(); std::list< std::vector >::const_iterator nodeDatait = data.begin(); ConsensusTransSetSF sf; @@ -151,12 +153,12 @@ bool TransactionAcquire::takeNodes(const std::list& nodeIDs, if (mHaveRoot) { cLog(lsWARNING) << "Got root TXS node, already have it"; - return false; + return SMAddNode(); } if (!mMap->addRootNode(getHash(), *nodeDatait, snfWIRE, NULL)) { cLog(lsWARNING) << "TX acquire got bad root node"; - return false; + return SMAddNode::invalid(); } else mHaveRoot = true; @@ -164,19 +166,19 @@ bool TransactionAcquire::takeNodes(const std::list& nodeIDs, else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait, &sf)) { cLog(lsWARNING) << "TX acquire got bad non-root node"; - return false; + return SMAddNode::invalid(); } ++nodeIDit; ++nodeDatait; } trigger(peer, false); progress(); - return true; + return SMAddNode::useful(); } catch (...) { cLog(lsERROR) << "Peer sends us junky transaction node data"; - return false; + return SMAddNode::invalid(); } } @@ -996,14 +998,14 @@ bool LedgerConsensus::peerHasSet(Peer::ref peer, const uint256& hashSet, ripple: return true; } -bool LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash, +SMAddNode LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData) { boost::unordered_map::iterator acq = mAcquiring.find(setHash); if (acq == mAcquiring.end()) { cLog(lsINFO) << "Got TX data for set not acquiring: " << setHash; - return false; + return SMAddNode(); } TransactionAcquire::pointer set = acq->second; // We must keep the set around during the function return set->takeNodes(nodeIDs, nodeData, peer); diff --git a/src/cpp/ripple/LedgerConsensus.h b/src/cpp/ripple/LedgerConsensus.h index 1db706996..accbb4df4 100644 --- a/src/cpp/ripple/LedgerConsensus.h +++ b/src/cpp/ripple/LedgerConsensus.h @@ -45,7 +45,8 @@ public: SHAMap::pointer getMap() { return mMap; } - bool takeNodes(const std::list& IDs, const std::list< std::vector >& data, Peer::ref); + SMAddNode takeNodes(const std::list& IDs, + const std::list< std::vector >& data, Peer::ref); }; class LCTransaction @@ -184,7 +185,7 @@ public: bool peerHasSet(Peer::ref peer, const uint256& set, ripple::TxSetStatus status); - bool peerGaveNodes(Peer::ref peer, const uint256& setHash, + SMAddNode peerGaveNodes(Peer::ref peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); bool isOurPubKey(const RippleAddress &k) { return k == mValPublic; } diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index ed4847f9b..21933a88b 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -813,13 +813,13 @@ SHAMap::pointer NetworkOPs::getTXMap(const uint256& hash) return mConsensus->getTransactionTree(hash, false); } -bool NetworkOPs::gotTXData(const boost::shared_ptr& peer, const uint256& hash, +SMAddNode NetworkOPs::gotTXData(const boost::shared_ptr& peer, const uint256& hash, const std::list& nodeIDs, const std::list< std::vector >& nodeData) { if (!haveConsensusObject()) { cLog(lsWARNING) << "Got TX data with no consensus object"; - return false; + return SMAddNode(); } return mConsensus->peerGaveNodes(peer, hash, nodeIDs, nodeData); } diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 778846a22..4826979e1 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -199,7 +199,7 @@ public: // ledger proposal/close functions void processTrustedProposal(LedgerProposal::pointer proposal, boost::shared_ptr set, RippleAddress nodePublic, uint256 checkLedger, bool sigGood); - bool gotTXData(const boost::shared_ptr& peer, const uint256& hash, + SMAddNode 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); SHAMap::pointer getTXMap(const uint256& hash); diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp index c42108e2e..fcca1754d 100644 --- a/src/cpp/ripple/Peer.cpp +++ b/src/cpp/ripple/Peer.cpp @@ -1432,12 +1432,14 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size())); nodeData.push_back(std::vector(node.nodedata().begin(), node.nodedata().end())); } - if (!theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData)) + SMAddNode san = theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData); + if (san.isInvalid()) punishPeer(PP_UNWANTED_DATA); return; } - if (!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this())) + SMAddNode san = theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()); + if (san.isInvalid()) punishPeer(PP_UNWANTED_DATA); } diff --git a/src/cpp/ripple/Peer.h b/src/cpp/ripple/Peer.h index f3c29c0f2..c05aac0d2 100644 --- a/src/cpp/ripple/Peer.h +++ b/src/cpp/ripple/Peer.h @@ -22,6 +22,12 @@ enum PeerPunish PP_BAD_SIGNATURE = 4, // Object had bad signature }; +enum PeerReward +{ + PR_NEEDED_DATA = 1, + PR_NEW_TRANSACTION = 2, +}; + typedef std::pair ipPort; DEFINE_INSTANCE(Peer); diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index c550a9749..1e4ab5d9b 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -213,12 +213,28 @@ void ProofOfWorkGenerator::sweep() void ProofOfWorkGenerator::loadHigh() { - // WRITEME + time_t now = time(NULL); + + boost::mutex::scoped_lock sl(mLock); + if (mLastDifficultyChange == now) + return; + if (mPowEntry == 30) + return; + ++mPowEntry; + mLastDifficultyChange = now; } void ProofOfWorkGenerator::loadLow() { - // WRITEME + time_t now = time(NULL); + + boost::mutex::scoped_lock sl(mLock); + if (mLastDifficultyChange == now) + return; + if (mPowEntry == 0) + return; + --mPowEntry; + mLastDifficultyChange = now; } struct PowEntry diff --git a/src/cpp/ripple/SHAMap.h b/src/cpp/ripple/SHAMap.h index 7adc92bc2..c4d830262 100644 --- a/src/cpp/ripple/SHAMap.h +++ b/src/cpp/ripple/SHAMap.h @@ -281,6 +281,44 @@ public: extern std::ostream& operator<<(std::ostream&, const SHAMapMissingNode&); +class SMAddNode +{ // results of adding nodes +protected: + bool mInvalid, mUseful; + + SMAddNode(bool i, bool u) : mInvalid(i), mUseful(u) { ; } + +public: + SMAddNode() : mInvalid(false), mUseful(false) { ; } + + void setInvalid() { mInvalid = true; } + void setUseful() { mUseful = true; } + void reset() { mInvalid = false; mUseful = false; } + + bool isInvalid() const { return mInvalid; } + bool isUseful() const { return mUseful; } + + bool combine(const SMAddNode& n) + { + if (n.mInvalid) + { + mInvalid = true; + return false; + } + if (n.mUseful) + mUseful = true; + return true; + } + + operator bool() const { return !mInvalid; } + + static SMAddNode okay() { return SMAddNode(false, false); } + static SMAddNode useful() { return SMAddNode(false, true); } + static SMAddNode invalid() { return SMAddNode(true, false); } +}; + +extern bool SMANCombine(SMAddNode& existing, const SMAddNode& additional); + class SHAMap : public IS_INSTANCE(SHAMap) { public: @@ -374,11 +412,11 @@ public: bool getNodeFat(const SHAMapNode& node, std::vector& nodeIDs, std::list >& rawNode, bool fatRoot, bool fatLeaves); bool getRootNode(Serializer& s, SHANodeFormat format); - bool addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format, + SMAddNode addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format, SHAMapSyncFilter* filter); - bool addRootNode(const std::vector& rootNode, SHANodeFormat format, + SMAddNode addRootNode(const std::vector& rootNode, SHANodeFormat format, SHAMapSyncFilter* filter); - bool addKnownNode(const SHAMapNode& nodeID, const std::vector& rawNode, + SMAddNode addKnownNode(const SHAMapNode& nodeID, const std::vector& rawNode, SHAMapSyncFilter* filter); // status functions diff --git a/src/cpp/ripple/SHAMapSync.cpp b/src/cpp/ripple/SHAMapSync.cpp index 5c419f106..7abcf9fd8 100644 --- a/src/cpp/ripple/SHAMapSync.cpp +++ b/src/cpp/ripple/SHAMapSync.cpp @@ -135,7 +135,8 @@ bool SHAMap::getRootNode(Serializer& s, SHANodeFormat format) return true; } -bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeFormat format, SHAMapSyncFilter* filter) +SMAddNode SHAMap::addRootNode(const std::vector& rootNode, SHANodeFormat format, + SHAMapSyncFilter* filter) { boost::recursive_mutex::scoped_lock sl(mLock); @@ -143,12 +144,12 @@ bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeForm if (root->getNodeHash().isNonZero()) { cLog(lsTRACE) << "got root node, already have one"; - return true; + return SMAddNode::okay(); } SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, format); if (!node) - return false; + return SMAddNode::invalid(); #ifdef DEBUG node->dump(); @@ -170,10 +171,10 @@ bool SHAMap::addRootNode(const std::vector& rootNode, SHANodeForm filter->gotNode(*root, root->getNodeHash(), s.peekData(), root->getType()); } - return true; + return SMAddNode::useful(); } -bool SHAMap::addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format, +SMAddNode SHAMap::addRootNode(const uint256& hash, const std::vector& rootNode, SHANodeFormat format, SHAMapSyncFilter* filter) { boost::recursive_mutex::scoped_lock sl(mLock); @@ -183,14 +184,12 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector& { cLog(lsTRACE) << "got root node, already have one"; assert(root->getNodeHash() == hash); - return true; + return SMAddNode::okay(); } SHAMapTreeNode::pointer node = boost::make_shared(SHAMapNode(), rootNode, 0, format); - if (!node) - return false; - if (node->getNodeHash() != hash) - return false; + if (!node || node->getNodeHash() != hash) + return SMAddNode::invalid(); returnNode(root, true); root = node; @@ -207,42 +206,42 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector& filter->gotNode(*root, root->getNodeHash(), s.peekData(), root->getType()); } - return true; + return SMAddNode::useful(); } -bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector& rawNode, +SMAddNode SHAMap::addKnownNode(const SHAMapNode& node, const std::vector& rawNode, SHAMapSyncFilter* filter) { // return value: true=okay, false=error assert(!node.isRoot()); if (!isSynching()) { cLog(lsINFO) << "AddKnownNode while not synching"; - return true; + return SMAddNode::okay(); } boost::recursive_mutex::scoped_lock sl(mLock); if (checkCacheNode(node)) - return true; + return SMAddNode::okay(); std::stack stack = getStack(node.getNodeID(), true, true); if (stack.empty()) { cLog(lsWARNING) << "AddKnownNode with empty stack"; - return false; + return SMAddNode::invalid(); } SHAMapTreeNode::pointer iNode = stack.top(); if (!iNode) { // we should always have a root assert(false); - return true; + return SMAddNode::invalid(); } if (iNode->isLeaf() || (iNode->getDepth() >= node.getDepth())) { cLog(lsTRACE) << "got inner node, already had it (late)"; - return true; + return SMAddNode::okay(); } if (iNode->getDepth() != (node.getDepth() - 1)) @@ -250,25 +249,25 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector(node, rawNode, mSeq, snfWIRE); if (hash != newNode->getNodeHash()) // these aren't the droids we're looking for - return false; + return SMAddNode::invalid(); if (filter) { @@ -279,7 +278,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorisLeaf()) - return true; // only a leaf can fill a branch + return SMAddNode::useful(); // only a leaf can fill a branch // did this new leaf cause its parents to fill up do @@ -294,11 +293,11 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgetChildNodeID(i), iNode->getChildHash(i), false); if (nextNode->isInner() && !nextNode->isFullBelow()) - return true; + return SMAddNode::useful(); } catch (SHAMapMissingNode&) { - return true; + return SMAddNode::useful(); } } iNode->setFullBelow(); @@ -306,7 +305,7 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorisFullBelow()) clearSynching(); - return true; + return SMAddNode::useful(); } bool SHAMap::deepCompare(SHAMap& other) @@ -486,6 +485,8 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test ) cLog(lsFATAL) << "Didn't get root node " << gotNodes.size(); BOOST_FAIL("NodeSize"); } + + SMAddNode node(); if (!destination.addRootNode(*gotNodes.begin(), snfWIRE, NULL)) { cLog(lsFATAL) << "AddRootNode fails"; From b4e7d8c5c39ec08080024fb684dd0cd2edfceb25 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 21 Nov 2012 09:49:00 -0800 Subject: [PATCH 3/9] Proof of work message structures --- src/cpp/ripple/ripple.proto | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/cpp/ripple/ripple.proto b/src/cpp/ripple/ripple.proto index 5ffbb657d..250ebf5ac 100644 --- a/src/cpp/ripple/ripple.proto +++ b/src/cpp/ripple/ripple.proto @@ -5,6 +5,7 @@ enum MessageType { mtHELLO = 1; mtERROR_MSG = 2; mtPING = 3; + mtPOW = 4; // network presence detection mtGET_CONTACTS = 10; @@ -32,20 +33,44 @@ enum MessageType { } -// Sent on connect +// empty message (or just result) = request proof of work +// token, iterations, target, challenge = give proof of work challenge +// token, response = show proof of work +// token, result = result of pow attempt +message TMProofWork +{ + optional string token = 1; + optional uint32 iterations = 2; + optional bytes target = 3; + optional bytes challenge = 4; + optional bytes response = 5; + enum POWResult + { + powrOK = 0; + powrREUSED = 1; + powrEXPIRED = 2; // You took too long solving + powrTOOEASY = 3; // Difficulty went way up, sorry + powrINVALID = 4; + powrDISCONNECT = 5; // We are disconnecting + } + optional POWResult result = 6; +} + +// Sent on connect message TMHello { - required uint32 protoVersion = 1; - required uint32 protoVersionMin = 2; - required bytes nodePublic = 3; - required bytes nodeProof = 4; - optional string fullVersion = 5; - optional uint64 netTime = 6; - optional uint32 ipv4Port = 7; - optional uint32 ledgerIndex = 8; - optional bytes ledgerClosed = 9; // our last closed ledger - optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger - optional bool nodePrivate = 11; // Request to not forward IP. + required uint32 protoVersion = 1; + required uint32 protoVersionMin = 2; + required bytes nodePublic = 3; + required bytes nodeProof = 4; + optional string fullVersion = 5; + optional uint64 netTime = 6; + optional uint32 ipv4Port = 7; + optional uint32 ledgerIndex = 8; + optional bytes ledgerClosed = 9; // our last closed ledger + optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger + optional bool nodePrivate = 11; // Request to not forward IP. + optional TMProofWork proofOfWork = 12; // request/provide proof of work } From 2c6b001b25ff71b01bd4dc814601bad41cc6a08c Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 21 Nov 2012 10:34:07 -0800 Subject: [PATCH 4/9] . --- src/cpp/ripple/Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/ripple/Config.h b/src/cpp/ripple/Config.h index 2caf47abf..53d91f692 100644 --- a/src/cpp/ripple/Config.h +++ b/src/cpp/ripple/Config.h @@ -21,7 +21,7 @@ #define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // rippled.cfg -#define DEFAULT_VALIDATORS_SITE "redstem.com" +#define DEFAULT_VALIDATORS_SITE "" #define VALIDATORS_FILE_NAME "validators.txt" const int SYSTEM_PEER_PORT = 6561; From 20f0ca6689be9921c75dc2b7451d41d142e7d8a9 Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 21 Nov 2012 10:54:07 -0800 Subject: [PATCH 5/9] windows --- newcoin.vcxproj | 1 + newcoin.vcxproj.filters | 3 +++ src/cpp/ripple/UniqueNodeList.cpp | 19 +++++++++++-------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 1891a5d7a..6a20b4ec2 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -124,6 +124,7 @@ + diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 064de313c..8b4cedd1e 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -342,6 +342,9 @@ Source Files + + Source Files + diff --git a/src/cpp/ripple/UniqueNodeList.cpp b/src/cpp/ripple/UniqueNodeList.cpp index 9b9c55a5d..df37f6d4d 100644 --- a/src/cpp/ripple/UniqueNodeList.cpp +++ b/src/cpp/ripple/UniqueNodeList.cpp @@ -1547,14 +1547,17 @@ void UniqueNodeList::validatorsResponse(const boost::system::error_code& err, st void UniqueNodeList::nodeNetwork() { - HttpsClient::httpsGet( - theApp->getIOService(), - theConfig.VALIDATORS_SITE, - 443, - VALIDATORS_FILE_PATH, - VALIDATORS_FILE_BYTES_MAX, - boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS), - boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2)); + if(!theConfig.VALIDATORS_SITE.empty()) + { + HttpsClient::httpsGet( + theApp->getIOService(), + theConfig.VALIDATORS_SITE, + 443, + VALIDATORS_FILE_PATH, + VALIDATORS_FILE_BYTES_MAX, + boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS), + boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2)); + } } void UniqueNodeList::nodeBootstrap() From c36d967de813d25beabc771bbf366e744ad5e95b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 21 Nov 2012 13:45:09 -0800 Subject: [PATCH 6/9] Fix a bug in TransactionMaster::fetch. Also, don't use this anyway. --- src/cpp/ripple/NetworkOPs.cpp | 21 ++++++++++----------- src/cpp/ripple/Serializer.h | 1 + src/cpp/ripple/TransactionMaster.cpp | 19 ++++++++++++++++--- src/cpp/ripple/TransactionMaster.h | 3 ++- src/cpp/ripple/TransactionMeta.h | 3 +++ 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 21933a88b..3ae6f2775 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1029,18 +1029,17 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted) for (SHAMapItem::pointer item = txSet.peekFirstItem(); !!item; item = txSet.peekNextItem(item->getTag())) { - SerializedTransaction::pointer stTxn = theApp->getMasterTransaction().fetch(item, false, 0); - if(stTxn) - { - // XXX Need to support other results. - // XXX Need to give failures too. - TER terResult = tesSUCCESS; - - SerializerIterator it(item->peekSerializer()); + SerializerIterator it(item->peekSerializer()); - TransactionMetaSet::pointer meta = boost::make_shared(stTxn->getTransactionID(), lpAccepted->getLedgerSeq(), it.getVL()); - pubAcceptedTransaction(lpAccepted, *stTxn, terResult,meta); - } + // OPTIMIZEME: Could get transaction from txn master, but still must call getVL + Serializer txnSer(it.getVL()); + SerializerIterator txnIt(txnSer); + SerializedTransaction stTxn(txnIt); + + TransactionMetaSet::pointer meta = boost::make_shared( + stTxn.getTransactionID(), lpAccepted->getLedgerSeq(), it.getVL()); + + pubAcceptedTransaction(lpAccepted, stTxn, meta->getResultTER(), meta); } } } diff --git a/src/cpp/ripple/Serializer.h b/src/cpp/ripple/Serializer.h index 7b7b67fe2..4bb929b19 100644 --- a/src/cpp/ripple/Serializer.h +++ b/src/cpp/ripple/Serializer.h @@ -93,6 +93,7 @@ public: // totality functions const std::vector& peekData() const { return mData; } std::vector getData() const { return mData; } + std::vector& modData() { return mData; } int getCapacity() const { return mData.capacity(); } int getDataLength() const { return mData.size(); } const void* getDataPtr() const { return &mData.front(); } diff --git a/src/cpp/ripple/TransactionMaster.cpp b/src/cpp/ripple/TransactionMaster.cpp index bfa0a8b72..ed6b575d6 100644 --- a/src/cpp/ripple/TransactionMaster.cpp +++ b/src/cpp/ripple/TransactionMaster.cpp @@ -31,16 +31,29 @@ Transaction::pointer TransactionMaster::fetch(const uint256& txnID, bool checkDi return txn; } -SerializedTransaction::pointer TransactionMaster::fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger) +SerializedTransaction::pointer TransactionMaster::fetch(SHAMapItem::ref item, SHAMapTreeNode::TNType type, + bool checkDisk, uint32 uCommitLedger) { SerializedTransaction::pointer txn; Transaction::pointer iTx = theApp->getMasterTransaction().fetch(item->getTag(), false); if (!iTx) { - SerializerIterator sit(item->peekSerializer()); - txn = boost::make_shared(boost::ref(sit)); + if (type == SHAMapTreeNode::tnTRANSACTION_NM) + { + SerializerIterator sit(item->peekSerializer()); + txn = boost::make_shared(boost::ref(sit)); + } + else if (type == SHAMapTreeNode::tnTRANSACTION_MD) + { + Serializer s; + int length; + item->peekSerializer().getVL(s.modData(), 0, length); + SerializerIterator sit(s); + + txn = boost::make_shared(boost::ref(sit)); + } } else { diff --git a/src/cpp/ripple/TransactionMaster.h b/src/cpp/ripple/TransactionMaster.h index 138c05c9c..2db5eb170 100644 --- a/src/cpp/ripple/TransactionMaster.h +++ b/src/cpp/ripple/TransactionMaster.h @@ -16,7 +16,8 @@ public: TransactionMaster(); Transaction::pointer fetch(const uint256&, bool checkDisk); - SerializedTransaction::pointer fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger); + SerializedTransaction::pointer fetch(SHAMapItem::ref item, SHAMapTreeNode:: TNType type, + bool checkDisk, uint32 uCommitLedger); // return value: true = we had the transaction already bool canonicalize(Transaction::pointer& txn, bool maybeNew); diff --git a/src/cpp/ripple/TransactionMeta.h b/src/cpp/ripple/TransactionMeta.h index a22058089..66f57b1cb 100644 --- a/src/cpp/ripple/TransactionMeta.h +++ b/src/cpp/ripple/TransactionMeta.h @@ -37,6 +37,8 @@ public: const uint256& getTxID() { return mTransactionID; } uint32 getLgrSeq() { return mLedger; } + int getResult() const { return mResult; } + TER getResultTER() const { return static_cast(mResult); } bool isNodeAffected(const uint256&) const; void setAffectedNode(const uint256&, SField::ref type, uint16 nodeType); @@ -45,6 +47,7 @@ public: const STObject& peekAffectedNode(const uint256&) const; //std::vector getAffectedAccounts(); + Json::Value getJson(int p) const { return getAsObject().getJson(p); } void addRaw(Serializer&, TER); From fd1468b71f7cba5122c31af50840721b2ff7cd94 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 21 Nov 2012 14:13:37 -0800 Subject: [PATCH 7/9] Remove broken lock. --- src/cpp/ripple/WSConnection.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/ripple/WSConnection.cpp b/src/cpp/ripple/WSConnection.cpp index 8030cdc67..875b18942 100644 --- a/src/cpp/ripple/WSConnection.cpp +++ b/src/cpp/ripple/WSConnection.cpp @@ -50,7 +50,6 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest) // Regular RPC command { - boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock()); jvResult["result"] = mRPCHandler.doCommand( jvRequest["command"].asString(), jvRequest.isMember("params") From 48bb22afac780f54689e59894fc47e920e9d6720 Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 21 Nov 2012 15:07:57 -0800 Subject: [PATCH 8/9] meta --- src/cpp/ripple/NetworkOPs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 3ae6f2775..53654ab45 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1134,6 +1134,7 @@ void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTr if (!notify.empty()) { Json::Value jvObj = transJson(stTxn, terResult, bAccepted, lpCurrent, "account"); + if(meta) jvObj["meta"]=meta->getJson(0); BOOST_FOREACH(InfoSub* ispListener, notify) { @@ -1193,7 +1194,7 @@ void NetworkOPs::subAccount(InfoSub* ispListener, const boost::unordered_set usisElement; usisElement.insert(ispListener); - mSubAccount.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement)); + subMap.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement)); } else { From 637269fb80d2905989392fd00486f5b86133cc43 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 21 Nov 2012 15:28:50 -0800 Subject: [PATCH 9/9] Traverse the correct object when generating modification metadata. Other small similar fixes. --- src/cpp/ripple/LedgerEntrySet.cpp | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index 1ff883fb5..59df4ec21 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -407,22 +407,26 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result) mSet.setAffectedNode(it.first, *type, nodeType); if (type == &sfDeletedNode) - { // nodes was deleted + { assert(origNode); assert(curNode); threadOwners(origNode, mLedger, newMod); // thread transaction to owners - STObject mods(sfPreviousFields); + STObject prevs(sfPreviousFields); + BOOST_FOREACH(const SerializedType& obj, *origNode) + { // go through the original node for modified fields saved on modification + if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) + prevs.addObject(obj); + } + if (!prevs.empty()) + mSet.getAffectedNode(it.first, *type).addObject(prevs); + STObject finals(sfFinalFields); BOOST_FOREACH(const SerializedType& obj, *curNode) - { - if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) - mods.addObject(obj); + { // go through the final node for final fields if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_DeleteFinal)) finals.addObject(obj); } - if (!mods.empty()) - mSet.getAffectedNode(it.first, *type).addObject(mods); if (!finals.empty()) mSet.getAffectedNode(it.first, *type).addObject(finals); } @@ -431,17 +435,21 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result) if (curNode->isThreadedType()) // thread transaction to node it modified threadTx(curNode, mLedger, newMod); - STObject mods(sfPreviousFields); - STObject finals(sfFinalFields); + STObject prevs(sfPreviousFields); BOOST_FOREACH(const SerializedType& obj, *origNode) { // search the original node for values saved on modify if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) - mods.addObject(obj); + prevs.addObject(obj); + } + if (!prevs.empty()) + mSet.getAffectedNode(it.first, *type).addObject(prevs); + + STObject finals(sfFinalFields); + BOOST_FOREACH(const SerializedType& obj, *curNode) + { // search the final node for values saved always if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_ChangeNew)) finals.addObject(obj); } - if (!mods.empty()) - mSet.getAffectedNode(it.first, *type).addObject(mods); if (!finals.empty()) mSet.getAffectedNode(it.first, *type).addObject(finals); }