Skip to content

Instantly share code, notes, and snippets.

@polarbeard
Last active February 3, 2016 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save polarbeard/db7909cba265c3c50c02 to your computer and use it in GitHub Desktop.
Save polarbeard/db7909cba265c3c50c02 to your computer and use it in GitHub Desktop.
diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp
--- a/bitcoin/src/bitcoinrpc.cpp ede2e19dd0ce3d03f54689cbeda30b4b36152f7e532b3d34f0f8c55bb292f7d25c149b88162d96a8208997237a32566d0e555aa7105bfed8175983d80ad892e6
+++ b/bitcoin/src/bitcoinrpc.cpp a71655bcd21408123e7be15f91803707bafca212787544d3e160855c170d596029847dc35ecd0f4dbe10f8e412bee114fba803d4e369c980d06691373106c18d
@@ -196,6 +196,42 @@
return (int)vNodes.size();
}
+Value getpeerinfo(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getpeerinfo\n"
+ "Returns data about each connected network node.");
+
+ Array ret;
+
+ CRITICAL_BLOCK(cs_vNodes)
+ {
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ {
+ CNodeStats stats;
+ pnode->CopyStats(stats);
+
+ Object obj;
+ obj.push_back(Pair("addr", stats.addr.ToString()));
+ obj.push_back(Pair("services", strprintf("%08"PRI64x, stats.nServices)));
+ obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
+ obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
+ obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
+ obj.push_back(Pair("version", stats.nVersion));
+ obj.push_back(Pair("subver", stats.strSubVer));
+ obj.push_back(Pair("inbound", stats.fInbound));
+ obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime));
+ obj.push_back(Pair("height", stats.nStartingHeight));
+ obj.push_back(Pair("banscore", stats.nMisbehavior));
+
+ ret.push_back(obj);
+ }
+ }
+
+ return ret;
+}
+
double GetDifficulty()
{
@@ -1850,6 +1886,7 @@
make_pair("getblockcount", &getblockcount),
make_pair("getblocknumber", &getblocknumber),
make_pair("getconnectioncount", &getconnectioncount),
+ make_pair("getpeerinfo", &getpeerinfo),
make_pair("getdifficulty", &getdifficulty),
make_pair("getgenerate", &getgenerate),
make_pair("setgenerate", &setgenerate),
@@ -1897,6 +1934,7 @@
"getblockcount",
"getblocknumber", // deprecated
"getconnectioncount",
+ "getpeerinfo",
"getdifficulty",
"getgenerate",
"setgenerate",
diff -uNr a/bitcoin/src/net.cpp b/bitcoin/src/net.cpp
--- a/bitcoin/src/net.cpp 31eb2cbdf4f83f10ae8a7cdd3a69312ba6eafbecfafbeddf7546ce99847bd4f2a674037e2b89a0a7b91c37127d9770501c265a7977edb0ae0b3a5964272692f9
+++ b/bitcoin/src/net.cpp 107ef79a59c51c006cbdb3f7a1e6c48771773c935b023da6459564f0485a0ae7701acfe8551b8bad4b2d5f7826ae2b9166a7e8373157d2afe84ba05b26310838
@@ -577,16 +577,20 @@
return false;
}
-
-
-
-
-
-
-
-
-
-
+void CNode::CopyStats(CNodeStats &stats)
+{
+ stats.nServices = nServices;
+ stats.nLastSend = nLastSend;
+ stats.nLastRecv = nLastRecv;
+ stats.nTimeConnected = nTimeConnected;
+ stats.addr = addr;
+ stats.nVersion = nVersion;
+ stats.strSubVer = strSubVer;
+ stats.fInbound = fInbound;
+ stats.nReleaseTime = nReleaseTime;
+ stats.nStartingHeight = nStartingHeight;
+ stats.nMisbehavior = nMisbehavior;
+}
void ThreadSocketHandler(void* parg)
{
diff -uNr a/bitcoin/src/net.h b/bitcoin/src/net.h
--- a/bitcoin/src/net.h bb842420bcc67752edf8e658524b135f499c5f8676557a6c12f47f204303e34bd73beabdf6e9146ba452947c4e5cd298529969fab90f16942f6bf0c1229f7043
+++ b/bitcoin/src/net.h 77ede4a59510c44c7167144c78cc0608430c50ff25b28201eb39ee69b0d4acbcce7374c4efd254304732c409b5799bc59557c3cb69a29c9f7c29ddd3d9e3a4a6
@@ -87,10 +87,21 @@
extern int fUseProxy;
extern CAddress addrProxy;
-
-
-
-
+class CNodeStats
+{
+public:
+ uint64 nServices;
+ int64 nLastSend;
+ int64 nLastRecv;
+ int64 nTimeConnected;
+ CAddress addr;
+ int nVersion;
+ std::string strSubVer;
+ bool fInbound;
+ int64 nReleaseTime;
+ int nStartingHeight;
+ int nMisbehavior;
+};
class CNode
{
@@ -590,6 +601,7 @@
static void ClearBanned(); // needed for unit testing
static bool IsBanned(unsigned int ip);
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
+ void CopyStats(CNodeStats &stats);
};
diff -uNr a/bitcoin/src/net.h.orig b/bitcoin/src/net.h.orig
--- a/bitcoin/src/net.h.orig false
+++ b/bitcoin/src/net.h.orig bb842420bcc67752edf8e658524b135f499c5f8676557a6c12f47f204303e34bd73beabdf6e9146ba452947c4e5cd298529969fab90f16942f6bf0c1229f7043
@@ -0,0 +1,696 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_NET_H
+#define BITCOIN_NET_H
+
+#include <deque>
+#include <boost/array.hpp>
+#include <boost/foreach.hpp>
+#include <openssl/rand.h>
+
+#include "protocol.h"
+
+class CAddrDB;
+class CRequestTracker;
+class CNode;
+class CBlockIndex;
+extern int nBestHeight;
+extern int nConnectTimeout;
+
+
+
+inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
+inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
+static const unsigned int PUBLISH_HOPS = 5;
+
+bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
+bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault = 0, bool fAllowPort = false);
+bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault = 0, bool fAllowPort = false);
+bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
+void AddressCurrentlyConnected(const CAddress& addr);
+CNode* FindNode(unsigned int ip);
+CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
+void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
+bool AnySubscribed(unsigned int nChannel);
+void MapPort(bool fMapPort);
+bool BindListenPort(std::string& strError=REF(std::string()));
+void StartNode(void* parg);
+bool StopNode();
+
+enum
+{
+ MSG_TX = 1,
+ MSG_BLOCK,
+};
+
+class CRequestTracker
+{
+public:
+ void (*fn)(void*, CDataStream&);
+ void* param1;
+
+ explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
+ {
+ fn = fnIn;
+ param1 = param1In;
+ }
+
+ bool IsNull()
+ {
+ return fn == NULL;
+ }
+};
+
+
+
+
+
+extern bool fClient;
+extern bool fAllowDNS;
+extern uint64 nLocalServices;
+extern CAddress addrLocalHost;
+extern uint64 nLocalHostNonce;
+extern boost::array<int, 10> vnThreadsRunning;
+
+extern std::vector<CNode*> vNodes;
+extern CCriticalSection cs_vNodes;
+extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
+extern CCriticalSection cs_mapAddresses;
+extern std::map<CInv, CDataStream> mapRelay;
+extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
+extern CCriticalSection cs_mapRelay;
+extern std::map<CInv, int64> mapAlreadyAskedFor;
+
+// Settings
+extern int fUseProxy;
+extern CAddress addrProxy;
+
+
+
+
+
+
+class CNode
+{
+public:
+ // socket
+ uint64 nServices;
+ SOCKET hSocket;
+ CDataStream vSend;
+ CDataStream vRecv;
+ CCriticalSection cs_vSend;
+ CCriticalSection cs_vRecv;
+ int64 nLastSend;
+ int64 nLastRecv;
+ int64 nLastSendEmpty;
+ int64 nTimeConnected;
+ unsigned int nHeaderStart;
+ unsigned int nMessageStart;
+ CAddress addr;
+ int nVersion;
+ std::string strSubVer;
+ bool fClient;
+ bool fInbound;
+ bool fNetworkNode;
+ bool fSuccessfullyConnected;
+ bool fDisconnect;
+protected:
+ int nRefCount;
+
+ // Denial-of-service detection/prevention
+ // Key is ip address, value is banned-until-time
+ static std::map<unsigned int, int64> setBanned;
+ static CCriticalSection cs_setBanned;
+ int nMisbehavior;
+
+public:
+ int64 nReleaseTime;
+ std::map<uint256, CRequestTracker> mapRequests;
+ CCriticalSection cs_mapRequests;
+ uint256 hashContinue;
+ CBlockIndex* pindexLastGetBlocksBegin;
+ uint256 hashLastGetBlocksEnd;
+ int nStartingHeight;
+
+ // flood relay
+ std::vector<CAddress> vAddrToSend;
+ std::set<CAddress> setAddrKnown;
+ bool fGetAddr;
+ std::set<uint256> setKnown;
+
+ // inventory based relay
+ std::set<CInv> setInventoryKnown;
+ std::vector<CInv> vInventoryToSend;
+ CCriticalSection cs_inventory;
+ std::multimap<int64, CInv> mapAskFor;
+
+ // publish and subscription
+ std::vector<char> vfSubscribe;
+
+ CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
+ {
+ nServices = 0;
+ hSocket = hSocketIn;
+ vSend.SetType(SER_NETWORK);
+ vSend.SetVersion(0);
+ vRecv.SetType(SER_NETWORK);
+ vRecv.SetVersion(0);
+ // Version 0.2 obsoletes 20 Feb 2012
+ if (GetTime() > 1329696000)
+ {
+ vSend.SetVersion(209);
+ vRecv.SetVersion(209);
+ }
+ nLastSend = 0;
+ nLastRecv = 0;
+ nLastSendEmpty = GetTime();
+ nTimeConnected = GetTime();
+ nHeaderStart = -1;
+ nMessageStart = -1;
+ addr = addrIn;
+ nVersion = 0;
+ strSubVer = "";
+ fClient = false; // set by version message
+ fInbound = fInboundIn;
+ fNetworkNode = false;
+ fSuccessfullyConnected = false;
+ fDisconnect = false;
+ nRefCount = 0;
+ nReleaseTime = 0;
+ hashContinue = 0;
+ pindexLastGetBlocksBegin = 0;
+ hashLastGetBlocksEnd = 0;
+ nStartingHeight = -1;
+ fGetAddr = false;
+ vfSubscribe.assign(256, false);
+ nMisbehavior = 0;
+
+ // Be shy and don't send version until we hear
+ if (!fInbound)
+ PushVersion();
+ }
+
+ ~CNode()
+ {
+ if (hSocket != INVALID_SOCKET)
+ {
+ closesocket(hSocket);
+ hSocket = INVALID_SOCKET;
+ }
+ }
+
+private:
+ CNode(const CNode&);
+ void operator=(const CNode&);
+public:
+
+
+ int GetRefCount()
+ {
+ return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
+ }
+
+ CNode* AddRef(int64 nTimeout=0)
+ {
+ if (nTimeout != 0)
+ nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
+ else
+ nRefCount++;
+ return this;
+ }
+
+ void Release()
+ {
+ nRefCount--;
+ }
+
+
+
+ void AddAddressKnown(const CAddress& addr)
+ {
+ setAddrKnown.insert(addr);
+ }
+
+ void PushAddress(const CAddress& addr)
+ {
+ // Known checking here is only to save space from duplicates.
+ // SendMessages will filter it again for knowns that were added
+ // after addresses were pushed.
+ if (addr.IsValid() && !setAddrKnown.count(addr))
+ vAddrToSend.push_back(addr);
+ }
+
+
+ void AddInventoryKnown(const CInv& inv)
+ {
+ CRITICAL_BLOCK(cs_inventory)
+ setInventoryKnown.insert(inv);
+ }
+
+ void PushInventory(const CInv& inv)
+ {
+ CRITICAL_BLOCK(cs_inventory)
+ if (!setInventoryKnown.count(inv))
+ vInventoryToSend.push_back(inv);
+ }
+
+ void AskFor(const CInv& inv)
+ {
+ // We're using mapAskFor as a priority queue,
+ // the key is the earliest time the request can be sent
+ int64& nRequestTime = mapAlreadyAskedFor[inv];
+ printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
+
+ // Make sure not to reuse time indexes to keep things in the same order
+ int64 nNow = (GetTime() - 1) * 1000000;
+ static int64 nLastTime;
+ ++nLastTime;
+ nNow = std::max(nNow, nLastTime);
+ nLastTime = nNow;
+
+ // Each retry is 2 minutes after the last
+ nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
+ mapAskFor.insert(std::make_pair(nRequestTime, inv));
+ }
+
+
+
+ void BeginMessage(const char* pszCommand)
+ {
+ ENTER_CRITICAL_SECTION(cs_vSend);
+ if (nHeaderStart != -1)
+ AbortMessage();
+ nHeaderStart = vSend.size();
+ vSend << CMessageHeader(pszCommand, 0);
+ nMessageStart = vSend.size();
+ if (fDebug) {
+ printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
+ printf("sending: %s ", pszCommand);
+ }
+ }
+
+ void AbortMessage()
+ {
+ if (nHeaderStart == -1)
+ return;
+ vSend.resize(nHeaderStart);
+ nHeaderStart = -1;
+ nMessageStart = -1;
+ LEAVE_CRITICAL_SECTION(cs_vSend);
+
+ if (fDebug)
+ printf("(aborted)\n");
+ }
+
+ void EndMessage()
+ {
+ if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
+ {
+ printf("dropmessages DROPPING SEND MESSAGE\n");
+ AbortMessage();
+ return;
+ }
+
+ if (nHeaderStart == -1)
+ return;
+
+ // Set the size
+ unsigned int nSize = vSend.size() - nMessageStart;
+ memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
+
+ // Set the checksum
+ if (vSend.GetVersion() >= 209)
+ {
+ uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
+ unsigned int nChecksum = 0;
+ memcpy(&nChecksum, &hash, sizeof(nChecksum));
+ assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
+ memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
+ }
+
+ if (fDebug) {
+ printf("(%d bytes)\n", nSize);
+ }
+
+ nHeaderStart = -1;
+ nMessageStart = -1;
+ LEAVE_CRITICAL_SECTION(cs_vSend);
+ }
+
+ void EndMessageAbortIfEmpty()
+ {
+ if (nHeaderStart == -1)
+ return;
+ int nSize = vSend.size() - nMessageStart;
+ if (nSize > 0)
+ EndMessage();
+ else
+ AbortMessage();
+ }
+
+
+
+ void PushVersion()
+ {
+ /// when NTP implemented, change to just nTime = GetAdjustedTime()
+ int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
+ CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
+ CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress("0.0.0.0") : addrLocalHost);
+ RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
+ PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
+ nLocalHostNonce, FormatSubVersion(CLIENT_NAME, VERSION), nBestHeight);
+ }
+
+
+
+
+ void PushMessage(const char* pszCommand)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1>
+ void PushMessage(const char* pszCommand, const T1& a1)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+
+ void PushRequest(const char* pszCommand,
+ void (*fn)(void*, CDataStream&), void* param1)
+ {
+ uint256 hashReply;
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
+
+ CRITICAL_BLOCK(cs_mapRequests)
+ mapRequests[hashReply] = CRequestTracker(fn, param1);
+
+ PushMessage(pszCommand, hashReply);
+ }
+
+ template<typename T1>
+ void PushRequest(const char* pszCommand, const T1& a1,
+ void (*fn)(void*, CDataStream&), void* param1)
+ {
+ uint256 hashReply;
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
+
+ CRITICAL_BLOCK(cs_mapRequests)
+ mapRequests[hashReply] = CRequestTracker(fn, param1);
+
+ PushMessage(pszCommand, hashReply, a1);
+ }
+
+ template<typename T1, typename T2>
+ void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
+ void (*fn)(void*, CDataStream&), void* param1)
+ {
+ uint256 hashReply;
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
+
+ CRITICAL_BLOCK(cs_mapRequests)
+ mapRequests[hashReply] = CRequestTracker(fn, param1);
+
+ PushMessage(pszCommand, hashReply, a1, a2);
+ }
+
+
+
+ void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
+ bool IsSubscribed(unsigned int nChannel);
+ void Subscribe(unsigned int nChannel, unsigned int nHops=0);
+ void CancelSubscribe(unsigned int nChannel);
+ void CloseSocketDisconnect();
+ void Cleanup();
+
+
+ // Denial-of-service detection/prevention
+ // The idea is to detect peers that are behaving
+ // badly and disconnect/ban them, but do it in a
+ // one-coding-mistake-won't-shatter-the-entire-network
+ // way.
+ // IMPORTANT: There should be nothing I can give a
+ // node that it will forward on that will make that
+ // node's peers drop it. If there is, an attacker
+ // can isolate a node and/or try to split the network.
+ // Dropping a node for sending stuff that is invalid
+ // now but might be valid in a later version is also
+ // dangerous, because it can cause a network split
+ // between nodes running old code and nodes running
+ // new code.
+ static void ClearBanned(); // needed for unit testing
+ static bool IsBanned(unsigned int ip);
+ bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
+};
+
+
+
+
+
+
+
+
+
+
+inline void RelayInventory(const CInv& inv)
+{
+ // Put on lists to offer to the other nodes
+ CRITICAL_BLOCK(cs_vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ pnode->PushInventory(inv);
+}
+
+template<typename T>
+void RelayMessage(const CInv& inv, const T& a)
+{
+ CDataStream ss(SER_NETWORK);
+ ss.reserve(10000);
+ ss << a;
+ RelayMessage(inv, ss);
+}
+
+template<>
+inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
+{
+ CRITICAL_BLOCK(cs_mapRelay)
+ {
+ // Expire old relay messages
+ while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
+ {
+ mapRelay.erase(vRelayExpiration.front().second);
+ vRelayExpiration.pop_front();
+ }
+
+ // Save original serialized message so newer versions are preserved
+ mapRelay[inv] = ss;
+ vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
+ }
+
+ RelayInventory(inv);
+}
+
+
+
+
+
+
+
+
+//
+// Templates for the publish and subscription system.
+// The object being published as T& obj needs to have:
+// a set<unsigned int> setSources member
+// specializations of AdvertInsert and AdvertErase
+// Currently implemented for CTable and CProduct.
+//
+
+template<typename T>
+void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
+{
+ // Add to sources
+ obj.setSources.insert(pfrom->addr.ip);
+
+ if (!AdvertInsert(obj))
+ return;
+
+ // Relay
+ CRITICAL_BLOCK(cs_vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
+ pnode->PushMessage("publish", nChannel, nHops, obj);
+}
+
+template<typename T>
+void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
+{
+ uint256 hash = obj.GetHash();
+
+ CRITICAL_BLOCK(cs_vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
+ pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
+
+ AdvertErase(obj);
+}
+
+template<typename T>
+void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
+{
+ // Remove a source
+ obj.setSources.erase(pfrom->addr.ip);
+
+ // If no longer supported by any sources, cancel it
+ if (obj.setSources.empty())
+ AdvertStopPublish(pfrom, nChannel, nHops, obj);
+}
+
+#endif
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJWshTiAAoJEBHMkEKSnTaC0CcP/1p/g4qnMLrefr9zpDRwd3gw
kGysVspgs6XVAtgm6cY+1PSxHNnH1A7fB00ihmVMjclz2B+NYrITu0bomj4U82hn
X21fdPZr5it+3QCo/dIUAF1T+P9zz1RzG2fOgviJsdmWgjccbKFJy2jITBN+G93X
jhNNvhG1/SIz4DjBJy9yzBribCrlhDNrIZh9+qpC8KKdWm1jNVh1xzee+3Ihmf6c
v70iapj3+fs2/YsgBWDpHkWcVmockekm5x5RT6WC6SSRKpcVRwixDWtViJEzGdtI
CGcA5I29pICJs3ZFGp5nJXYTJxzfPgCno6K6c4299nKSgri2BQePqjnOmgI9aUvR
Mo+9IrkyU7Ue7/b3kB6gflO0oWZdSdO07c2M3m5F1ZZAswc9pVi+7IDfWLt5OTpf
NXZs2imWXdT8aRzlf+b3fJKZKWR3uDLCwWIeNN0EfAl3FFtXiynKDNl+riB9FHo9
BoJMv383YLxqzaWt7CLdpfnTYt9arYUtku5tVBIv6kkYDowNx8/gZNwvu2Gqj3nM
jktkQMUjyrUNg64IE80rILfLnGKpymtqL7KL4uwdjYg7R2wlBaueOct8GnQuU6Y1
Z5cg2a8GOdgFUcwa7oLDIyJAtbW7TBl8f7E1yXnWA00fJbtCyBQ7UUdIsG3JBjcm
Xv+qpzOe0zoerOpRBUVP
=znyv
-----END PGP SIGNATURE-----
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment