diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp index 632d6d7faf..4d3ab2625f 100644 --- a/src/cpp/ripple/LedgerAcquire.cpp +++ b/src/cpp/ripple/LedgerAcquire.cpp @@ -229,14 +229,16 @@ void LedgerAcquire::trigger(Peer::ref peer) { tmGL.set_querytype(ripple::qtINDIRECT); -#if 0 if (!isProgress()) { std::vector need = getNeededHashes(); if (!need.empty()) { ripple::TMGetObjectByHash tmBH; + tmBH.set_query(true); tmBH.set_ledgerhash(mHash.begin(), mHash.size()); + if (mHaveBase) + tmBH.set_seq(mLedger->getLedgerSeq()); bool typeSet = false; BOOST_FOREACH(neededHash_t& p, need) { @@ -247,17 +249,27 @@ void LedgerAcquire::trigger(Peer::ref peer) } if (p.first == tmBH.type()) { - // WRITEME: Approve this hash for local inclusion + theApp->getOPs().addWantedHash(p.second); ripple::TMIndexedObject *io = tmBH.add_objects(); io->set_hash(p.second.begin(), p.second.size()); } } - - // WRITEME: Do something with this object - + PackedMessage::pointer packet = boost::make_shared(tmBH, ripple::mtGET_OBJECTS); + if (peer) + peer->sendPacket(packet); + else + { + boost::recursive_mutex::scoped_lock sl(mLock); + for (boost::unordered_map::iterator it = mPeers.begin(), end = mPeers.end(); + it != end; ++it) + { + Peer::pointer iPeer = theApp->getConnectionPool().getPeerById(it->first); + if (iPeer) + iPeer->sendPacket(packet); + } + } } } -#endif } diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 5eb9b8e5f3..daacb52153 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -15,6 +15,7 @@ LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int deb addLoadCost(LoadCost(LT_RequestNoReply, 1, LC_CPU | LC_Disk)); addLoadCost(LoadCost(LT_InvalidSignature, 100, LC_CPU)); addLoadCost(LoadCost(LT_UnwantedData, 5, LC_CPU | LC_Network)); + addLoadCost(LoadCost(LT_BadData, 20, LC_CPU)); addLoadCost(LoadCost(LT_NewTrusted, 10, 0)); addLoadCost(LoadCost(LT_NewTransaction, 2, 0)); diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 22baff69a3..0cecd6c1e1 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -18,6 +18,7 @@ enum LoadType LT_InvalidSignature, // An object whose signature we had to check and it failed LT_UnwantedData, // Data we have no use for LT_BadPoW, // Proof of work not valid + LT_BadData, // Data we have to verify before rejecting // Good things LT_NewTrusted, // A new transaction/validation/proposal we trust diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index fc10d02362..13e917e56d 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -100,6 +100,18 @@ bool NetworkOPs::haveLedgerRange(uint32 from, uint32 to) return mLedgerMaster->haveLedgerRange(from, to); } +bool NetworkOPs::addWantedHash(const uint256& h) +{ + boost::recursive_mutex::scoped_lock sl(mWantedHashLock); + return mWantedHashes.insert(h).second; +} + +bool NetworkOPs::isWantedHash(const uint256& h, bool remove) +{ + boost::recursive_mutex::scoped_lock sl(mWantedHashLock); + return (remove ? mWantedHashes.erase(h) : mWantedHashes.count(h)) != 0; +} + void NetworkOPs::submitTransaction(Job&, SerializedTransaction::pointer iTrans, stCallback callback) { // this is an asynchronous interface Serializer s; diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 180a06ff8b..0bc53601be 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -108,6 +108,9 @@ protected: boost::unordered_set mSubTransactions; // all accepted transactions boost::unordered_set mSubRTTransactions; // all proposed and accepted transactions + boost::recursive_mutex mWantedHashLock; + boost::unordered_set mWantedHashes; + void setMode(OperatingMode); Json::Value transJson(const SerializedTransaction& stTxn, TER terResult, bool bAccepted, Ledger::ref lpCurrent, const std::string& strType); @@ -245,6 +248,9 @@ public: void storeProposal(const LedgerProposal::pointer& proposal, const RippleAddress& peerPublic); uint256 getConsensusLCL(); + bool addWantedHash(const uint256& h); + bool isWantedHash(const uint256& h, bool remove); + // client information retrieval functions std::vector< std::pair > getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger); diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp index c1b3676abd..d3fbd0e9c1 100644 --- a/src/cpp/ripple/Peer.cpp +++ b/src/cpp/ripple/Peer.cpp @@ -1111,6 +1111,8 @@ void Peer::recvGetObjectByHash(ripple::TMGetObjectByHash& packet) newObj.set_data(&hObj->getData().front(), hObj->getData().size()); if (obj.has_nodeid()) newObj.set_index(obj.nodeid()); + if (!packet.has_seq() && (hObj->getIndex() != 0)) + packet.set_seq(hObj->getIndex()); } } } @@ -1119,7 +1121,37 @@ void Peer::recvGetObjectByHash(ripple::TMGetObjectByHash& packet) } else { // this is a reply - // WRITEME + uint32 seq = packet.has_seq() ? packet.seq() : 0; + HashedObjectType type; + switch (packet.type()) + { + case ripple::TMGetObjectByHash::otLEDGER: type = hotLEDGER; break; + case ripple::TMGetObjectByHash::otTRANSACTION: type = hotTRANSACTION; break; + case ripple::TMGetObjectByHash::otSTATE_NODE: type = hotACCOUNT_NODE; break; + case ripple::TMGetObjectByHash::otTRANSACTION_NODE: type = hotTRANSACTION_NODE; break; + default: type = hotUNKNOWN; + } + for (int i = 0; i < packet.objects_size(); ++i) + { + const ripple::TMIndexedObject& obj = packet.objects(i); + if (obj.has_hash() && (obj.hash().size() == (256/8))) + { + uint256 hash; + memcpy(hash.begin(), obj.hash().data(), 256 / 8); + if (theApp->getOPs().isWantedHash(hash, true)) + { + std::vector data(obj.data().begin(), obj.data().end()); + if (Serializer::getSHA512Half(data) != hash) + { + cLog(lsWARNING) << "Bad hash in data from peer"; + theApp->getOPs().addWantedHash(hash); + punishPeer(LT_BadData); + } + else + theApp->getHashedObjectStore().store(type, seq, data, hash); + } + } + } } }