Feeler connections ported from BTC core, eclipse attack mitigation
This commit is contained in:
21
src/main.cpp
21
src/main.cpp
@@ -6862,10 +6862,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprintf(stderr,"netmsg: %s\n", strCommand.c_str());
|
fprintf(stderr,"%s: netmsg: %s from %s\n", __func__, strCommand.c_str(), pfrom->addr.ToString().c_str() );
|
||||||
|
|
||||||
|
if (strCommand == "version") {
|
||||||
|
// Feeler connections exist only to verify if node is online
|
||||||
|
if (pfrom->fFeeler) {
|
||||||
|
assert(pfrom->fInbound == false);
|
||||||
|
pfrom->fDisconnect = true;
|
||||||
|
fprintf(stderr,"%s: disconnecting feelerconn from %s\n", __func__, pfrom->addr.ToString().c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
if (strCommand == "version")
|
|
||||||
{
|
|
||||||
// Each connection can only send one version message
|
// Each connection can only send one version message
|
||||||
if (pfrom->nVersion != 0)
|
if (pfrom->nVersion != 0)
|
||||||
{
|
{
|
||||||
@@ -6978,15 +6984,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do Not Relay alerts
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
LOCK(cs_mapAlerts);
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
|
||||||
item.second.RelayTo(pfrom);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
pfrom->fSuccessfullyConnected = true;
|
pfrom->fSuccessfullyConnected = true;
|
||||||
|
|
||||||
string remoteAddr;
|
string remoteAddr;
|
||||||
|
|||||||
103
src/net.cpp
103
src/net.cpp
@@ -62,6 +62,9 @@ using namespace hush;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
|
||||||
|
#define FEELER_SLEEP_WINDOW 1
|
||||||
|
|
||||||
#define USE_TLS "encrypted as fuck"
|
#define USE_TLS "encrypted as fuck"
|
||||||
|
|
||||||
#if defined(USE_TLS) && !defined(TLS1_3_VERSION)
|
#if defined(USE_TLS) && !defined(TLS1_3_VERSION)
|
||||||
@@ -75,6 +78,7 @@ using namespace std;
|
|||||||
namespace {
|
namespace {
|
||||||
//TODO: Make these CLI args
|
//TODO: Make these CLI args
|
||||||
const int MAX_OUTBOUND_CONNECTIONS = 64;
|
const int MAX_OUTBOUND_CONNECTIONS = 64;
|
||||||
|
const int MAX_FEELER_CONNECTIONS = 1;
|
||||||
const int MAX_INBOUND_FROMIP = 3;
|
const int MAX_INBOUND_FROMIP = 3;
|
||||||
|
|
||||||
struct ListenSocket {
|
struct ListenSocket {
|
||||||
@@ -1023,8 +1027,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
|
|||||||
socklen_t len = sizeof(sockaddr);
|
socklen_t len = sizeof(sockaddr);
|
||||||
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
|
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
int nInbound = 0;
|
int nInbound = 0;
|
||||||
int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
|
int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS);
|
||||||
|
|
||||||
if (hSocket != INVALID_SOCKET)
|
if (hSocket != INVALID_SOCKET)
|
||||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||||
@@ -1412,6 +1416,11 @@ void static ProcessOneShot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t PoissonNextSend(int64_t now, int average_interval_seconds)
|
||||||
|
{
|
||||||
|
return now + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
void ThreadOpenConnections()
|
void ThreadOpenConnections()
|
||||||
{
|
{
|
||||||
// Connect to specific addresses
|
// Connect to specific addresses
|
||||||
@@ -1436,8 +1445,11 @@ void ThreadOpenConnections()
|
|||||||
|
|
||||||
// Initiate network connections
|
// Initiate network connections
|
||||||
int64_t nStart = GetTime();
|
int64_t nStart = GetTime();
|
||||||
while (true)
|
|
||||||
{
|
// Minimum time before next feeler connection (in microseconds).
|
||||||
|
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
ProcessOneShot();
|
ProcessOneShot();
|
||||||
|
|
||||||
MilliSleep(500);
|
MilliSleep(500);
|
||||||
@@ -1450,19 +1462,17 @@ void ThreadOpenConnections()
|
|||||||
if (GetTime() - nStart > 60) {
|
if (GetTime() - nStart > 60) {
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
if (!done) {
|
if (!done) {
|
||||||
// skip DNS seeds for staked chains.
|
|
||||||
LogPrintf("Adding fixed seed nodes.\n");
|
LogPrintf("Adding fixed seed nodes.\n");
|
||||||
addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
|
addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Choose an address to connect to based on most recently seen
|
// Choose an address to connect to based on most recently seen
|
||||||
CAddress addrConnect;
|
CAddress addrConnect;
|
||||||
|
|
||||||
// Only connect out to one peer per network group (/16 for IPv4).
|
// Only connect out to one peer per network group. Originally /16 for IPv4, now ASNs via
|
||||||
// Use -asmap for ASN bucketing
|
// -asmap for ASN bucketing, which is enabled by default
|
||||||
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
||||||
int nOutbound = 0;
|
int nOutbound = 0;
|
||||||
set<vector<unsigned char> > setConnected;
|
set<vector<unsigned char> > setConnected;
|
||||||
@@ -1475,13 +1485,38 @@ void ThreadOpenConnections()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS));
|
||||||
|
|
||||||
|
// "Feeler Connections" as per https://eprint.iacr.org/2015/263.pdf
|
||||||
|
// "Eclipse Attacks on Bitcoin’s Peer-to-Peer Network" by
|
||||||
|
// Ethan Heilman, Alison Kendler, Aviv Zohar, Sharon Goldberg.
|
||||||
|
//
|
||||||
|
// Design goals:
|
||||||
|
// * Increase the number of connectable addresses in the tried table.
|
||||||
|
//
|
||||||
|
// Method:
|
||||||
|
// * Choose a random address from new and attempt to connect to it if we can connect
|
||||||
|
// successfully it is added to tried.
|
||||||
|
// * Start attempting feeler connections only after node finishes making outbound
|
||||||
|
// connections.
|
||||||
|
// * Make feeler connections randomly with 120s average interval via PoissonNextSend.
|
||||||
|
// Originally from https://github.com/bitcoin/bitcoin/pull/8282
|
||||||
|
// Modified for API changes by Duke Leto
|
||||||
|
bool fFeeler = false;
|
||||||
|
if (nOutbound >= MAX_OUTBOUND_CONNECTIONS) {
|
||||||
|
int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds).
|
||||||
|
if (nTime > nNextFeeler) {
|
||||||
|
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
|
||||||
|
fFeeler = true;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64_t nANow = GetTime();
|
int64_t nANow = GetTime();
|
||||||
|
int nTries = 0;
|
||||||
int nTries = 0;
|
while (true) {
|
||||||
while (true)
|
CAddrInfo addr = addrman.Select(fFeeler);
|
||||||
{
|
|
||||||
CAddrInfo addr = addrman.Select();
|
|
||||||
|
|
||||||
// if we selected an invalid address, restart
|
// if we selected an invalid address, restart
|
||||||
if (!addr.IsValid() || setConnected.count(addr.GetGroup(addrman.m_asmap)) || IsLocal(addr))
|
if (!addr.IsValid() || setConnected.count(addr.GetGroup(addrman.m_asmap)) || IsLocal(addr))
|
||||||
@@ -1501,6 +1536,13 @@ void ThreadOpenConnections()
|
|||||||
if (nANow - addr.nLastTry < 600 && nTries < 30)
|
if (nANow - addr.nLastTry < 600 && nTries < 30)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* TODO: port this code
|
||||||
|
// only consider nodes missing relevant services after 40 failed attempts
|
||||||
|
if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40)
|
||||||
|
continue;
|
||||||
|
*/
|
||||||
|
|
||||||
|
//TODO: why is this a good thing?
|
||||||
// do not allow non-default ports, unless after 50 invalid addresses selected already
|
// do not allow non-default ports, unless after 50 invalid addresses selected already
|
||||||
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
|
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
|
||||||
continue;
|
continue;
|
||||||
@@ -1509,8 +1551,18 @@ void ThreadOpenConnections()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addrConnect.IsValid())
|
if (addrConnect.IsValid()) {
|
||||||
OpenNetworkConnection(addrConnect, &grant);
|
if (fFeeler) {
|
||||||
|
// Add small amount of random noise before connection to avoid synchronization
|
||||||
|
int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
|
||||||
|
MilliSleep(randsleep);
|
||||||
|
LogPrint("net", "Making feeler connection to %s\n", addrConnect.ToString().c_str());
|
||||||
|
printf("%s: Making feeler connection to %s\n", __func__, addrConnect.ToString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//int failures = setConnected.size() >= std::min(nMaxConnections - 1, 2);
|
||||||
|
OpenNetworkConnection(addrConnect,/*failures,*/ &grant, NULL, false, fFeeler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,7 +1643,7 @@ void ThreadOpenAddedConnections()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if successful, this moves the passed grant to the constructed node
|
// if successful, this moves the passed grant to the constructed node
|
||||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
|
bool OpenNetworkConnection(const CAddress& addrConnect, /* bool fCountFailure, */ CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler)
|
||||||
{
|
{
|
||||||
// Initiate outbound network connection
|
// Initiate outbound network connection
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
@@ -1604,6 +1656,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
CNode* pnode = ConnectNode(addrConnect, pszDest);
|
CNode* pnode = ConnectNode(addrConnect, pszDest);
|
||||||
|
//CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure);
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
|
|
||||||
if (!pnode)
|
if (!pnode)
|
||||||
@@ -1611,8 +1664,11 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
|
|||||||
if (grantOutbound)
|
if (grantOutbound)
|
||||||
grantOutbound->MoveTo(pnode->grantOutbound);
|
grantOutbound->MoveTo(pnode->grantOutbound);
|
||||||
pnode->fNetworkNode = true;
|
pnode->fNetworkNode = true;
|
||||||
|
|
||||||
if (fOneShot)
|
if (fOneShot)
|
||||||
pnode->fOneShot = true;
|
pnode->fOneShot = true;
|
||||||
|
if (fFeeler)
|
||||||
|
pnode->fFeeler = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1858,7 +1914,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
|
|
||||||
if (semOutbound == NULL) {
|
if (semOutbound == NULL) {
|
||||||
// initialize semaphore
|
// initialize semaphore
|
||||||
int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
|
int nMaxOutbound = min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections);
|
||||||
semOutbound = new CSemaphore(nMaxOutbound);
|
semOutbound = new CSemaphore(nMaxOutbound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1907,7 +1963,7 @@ bool StopNode()
|
|||||||
{
|
{
|
||||||
LogPrintf("StopNode()\n");
|
LogPrintf("StopNode()\n");
|
||||||
if (semOutbound)
|
if (semOutbound)
|
||||||
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
|
for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++)
|
||||||
semOutbound->post();
|
semOutbound->post();
|
||||||
|
|
||||||
if (HUSH_NSPV_FULLNODE && fAddressesInitialized)
|
if (HUSH_NSPV_FULLNODE && fAddressesInitialized)
|
||||||
@@ -2166,12 +2222,13 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
|
|||||||
nTimeOffset = 0;
|
nTimeOffset = 0;
|
||||||
addr = addrIn;
|
addr = addrIn;
|
||||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||||
nVersion = 0;
|
nVersion = 0;
|
||||||
strSubVer = "";
|
strSubVer = "";
|
||||||
fAllowlisted = false;
|
fAllowlisted = false;
|
||||||
fOneShot = false;
|
fOneShot = false;
|
||||||
fClient = false; // set by version message
|
fClient = false; // set by version message
|
||||||
fInbound = fInboundIn;
|
fFeeler = false;
|
||||||
|
fInbound = fInboundIn;
|
||||||
fNetworkNode = false;
|
fNetworkNode = false;
|
||||||
fSuccessfullyConnected = false;
|
fSuccessfullyConnected = false;
|
||||||
fDisconnect = false;
|
fDisconnect = false;
|
||||||
|
|||||||
14
src/net.h
14
src/net.h
@@ -82,10 +82,13 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
|
|||||||
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 384;
|
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 384;
|
||||||
/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
|
/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
|
||||||
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
|
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
|
||||||
|
/** Run the feeler connection loop once every 120 seconds. **/
|
||||||
|
static const int FEELER_INTERVAL = 120;
|
||||||
|
|
||||||
unsigned int ReceiveFloodSize();
|
unsigned int ReceiveFloodSize();
|
||||||
unsigned int SendBufferSize();
|
unsigned int SendBufferSize();
|
||||||
|
|
||||||
|
int64_t PoissonNextSend(int64_t now, int average_interval_seconds);
|
||||||
void AddOneShot(const std::string& strDest);
|
void AddOneShot(const std::string& strDest);
|
||||||
void AddressCurrentlyConnected(const CService& addr);
|
void AddressCurrentlyConnected(const CService& addr);
|
||||||
CNode* FindNode(const CNetAddr& ip);
|
CNode* FindNode(const CNetAddr& ip);
|
||||||
@@ -93,7 +96,7 @@ CNode* FindNode(const CSubNet& subNet);
|
|||||||
CNode* FindNode(const std::string& addrName);
|
CNode* FindNode(const std::string& addrName);
|
||||||
CNode* FindNode(const CService& ip);
|
CNode* FindNode(const CService& ip);
|
||||||
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
|
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
|
||||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
|
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
||||||
unsigned short GetListenPort();
|
unsigned short GetListenPort();
|
||||||
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fAllowlisted = false);
|
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fAllowlisted = false);
|
||||||
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler);
|
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler);
|
||||||
@@ -220,7 +223,8 @@ public:
|
|||||||
int nStartingHeight;
|
int nStartingHeight;
|
||||||
uint64_t nSendBytes;
|
uint64_t nSendBytes;
|
||||||
uint64_t nRecvBytes;
|
uint64_t nRecvBytes;
|
||||||
bool fAllowlisted;
|
bool fAllowlisted; // If true this node bypasses DoS ban limits
|
||||||
|
bool fFeeler; // If true this node is being used as a short lived feeler.
|
||||||
double dPingTime;
|
double dPingTime;
|
||||||
double dPingWait;
|
double dPingWait;
|
||||||
std::string addrLocal;
|
std::string addrLocal;
|
||||||
@@ -228,7 +232,7 @@ public:
|
|||||||
CAddress addr;
|
CAddress addr;
|
||||||
// Bind address of our side of the connection
|
// Bind address of our side of the connection
|
||||||
// CAddress addrBind; // https://github.com/bitcoin/bitcoin/commit/a7e3c2814c8e49197889a4679461be42254e5c51
|
// CAddress addrBind; // https://github.com/bitcoin/bitcoin/commit/a7e3c2814c8e49197889a4679461be42254e5c51
|
||||||
uint32_t m_mapped_as;
|
uint32_t m_mapped_as; // Mapped ASN for this address
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -273,9 +277,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Information about a peer */
|
/** Information about a peer */
|
||||||
class CNode
|
class CNode
|
||||||
{
|
{
|
||||||
@@ -323,6 +324,7 @@ public:
|
|||||||
bool fOneShot;
|
bool fOneShot;
|
||||||
bool fClient;
|
bool fClient;
|
||||||
bool fInbound;
|
bool fInbound;
|
||||||
|
bool fFeeler;
|
||||||
bool fNetworkNode;
|
bool fNetworkNode;
|
||||||
bool fSuccessfullyConnected;
|
bool fSuccessfullyConnected;
|
||||||
bool fDisconnect;
|
bool fDisconnect;
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
|
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@@ -24,6 +22,35 @@ BOOST_AUTO_TEST_CASE(netbase_networks)
|
|||||||
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_ONION);
|
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_ONION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: port this feeler test
|
||||||
|
BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
|
{
|
||||||
|
SOCKET hSocket = INVALID_SOCKET;
|
||||||
|
|
||||||
|
in_addr ipv4Addr;
|
||||||
|
ipv4Addr.s_addr = 0xa0b0c001;
|
||||||
|
|
||||||
|
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
|
||||||
|
std::string pszDest = "";
|
||||||
|
bool fInboundIn = false;
|
||||||
|
|
||||||
|
// Test that fFeeler is false by default.
|
||||||
|
CNode* pnode1 = new CNode(hSocket, addr, pszDest, fInboundIn);
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_CHECK(pnode1->fInbound == false);
|
||||||
|
BOOST_CHECK(pnode1->fFeeler == false);
|
||||||
|
|
||||||
|
fInboundIn = true;
|
||||||
|
CNode* pnode2 = new CNode(hSocket, addr, pszDest, fInboundIn);
|
||||||
|
BOOST_CHECK(pnode2->fInbound == true);
|
||||||
|
BOOST_CHECK(pnode2->fFeeler == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(netbase_properties)
|
BOOST_AUTO_TEST_CASE(netbase_properties)
|
||||||
{
|
{
|
||||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
|
BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
|
||||||
|
|||||||
Reference in New Issue
Block a user